From 9219db4c2a4dbb0709cc0f893622262cc4defc2e Mon Sep 17 00:00:00 2001 From: Saurabh Date: Fri, 16 Oct 2020 14:09:35 +0530 Subject: [PATCH 001/187] fix: validate email id before passing to formataddr --- frappe/utils/__init__.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index d3bf1dd10c..9640bcd394 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -66,9 +66,14 @@ def get_email_address(user=None): def get_formatted_email(user, mail=None): """get Email Address of user formatted as: `John Doe `""" fullname = get_fullname(user) + if not mail: - mail = get_email_address(user) - return cstr(make_header(decode_header(formataddr((fullname, mail))))) + mail = get_email_address(user) or validate_email_address(user) + + if not mail: + return '' + else: + return cstr(make_header(decode_header(formataddr((fullname, mail))))) def extract_email_id(email): """fetch only the email part of the Email Address""" From f71a8e0afcffae02dee34fd20642ee439c6b6017 Mon Sep 17 00:00:00 2001 From: everyx Date: Tue, 24 Nov 2020 14:36:53 +0800 Subject: [PATCH 002/187] fix: `PRIMARY KEY must be NOT NULL` error when install with MySQL 5.7+ --- frappe/database/mariadb/framework_mariadb.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/database/mariadb/framework_mariadb.sql b/frappe/database/mariadb/framework_mariadb.sql index 15b0bed699..a52efd01e3 100644 --- a/frappe/database/mariadb/framework_mariadb.sql +++ b/frappe/database/mariadb/framework_mariadb.sql @@ -233,7 +233,7 @@ CREATE TABLE `tabDocType` ( DROP TABLE IF EXISTS `tabSeries`; CREATE TABLE `tabSeries` ( - `name` varchar(100) DEFAULT NULL, + `name` varchar(100), `current` int(10) NOT NULL DEFAULT 0, PRIMARY KEY(`name`) ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8mb4 COLLATE=utf8mb4_unicode_ci; From 926d7e78fd75dcfc5713de7c684900d54d84a843 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 26 Nov 2020 15:33:55 +0530 Subject: [PATCH 003/187] fix: clear localstorage if quota exceeds --- frappe/public/js/frappe/model/model.js | 33 +++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/frappe/public/js/frappe/model/model.js b/frappe/public/js/frappe/model/model.js index 308d9bd5f8..1d302215dd 100644 --- a/frappe/public/js/frappe/model/model.js +++ b/frappe/public/js/frappe/model/model.js @@ -103,6 +103,31 @@ $.extend(frappe.model, { return docfield[0]; }, + get_from_localstorage: function(doctype) { + if (localStorage["_doctype:" + doctype]) { + return JSON.parse(localStorage["_doctype:" + doctype]); + } + }, + + set_in_localstorage: function(doctype, docs) { + try { + localStorage["_doctype:" + doctype] = JSON.stringify(docs); + } catch(e) { + // if quota is exceeded, clear local storage and set item + console.warn("localStorage quota exceeded, clearing doctype cache") + frappe.model.clear_local_storage(); + localStorage["_doctype:" + doctype] = JSON.stringify(docs); + } + }, + + clear_local_storage: function() { + for(var key in localStorage) { + if (key.startsWith("_doctype:")) { + localStorage.removeItem(key); + } + } + }, + with_doctype: function(doctype, callback, async) { if(locals.DocType[doctype]) { callback && callback(); @@ -110,13 +135,15 @@ $.extend(frappe.model, { let cached_timestamp = null; let cached_doc = null; - if(localStorage["_doctype:" + doctype]) { - let cached_docs = JSON.parse(localStorage["_doctype:" + doctype]); + let cached_docs = frappe.model.get_from_localstorage(doctype) + + if (cached_docs) { cached_doc = cached_docs.filter(doc => doc.name === doctype)[0]; if(cached_doc) { cached_timestamp = cached_doc.modified; } } + return frappe.call({ method:'frappe.desk.form.load.getdoctype', type: "GET", @@ -134,7 +161,7 @@ $.extend(frappe.model, { if(r.message=="use_cache") { frappe.model.sync(cached_doc); } else { - localStorage["_doctype:" + doctype] = JSON.stringify(r.docs); + frappe.model.set_in_localstorage(doctype, r.docs) } frappe.model.init_doctype(doctype); From 8192db7382a02fd4334c227ad15339c10f7bede5 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 26 Nov 2020 16:22:40 +0530 Subject: [PATCH 004/187] chore: remove stray console --- frappe/public/js/frappe/desk.js | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/public/js/frappe/desk.js b/frappe/public/js/frappe/desk.js index c8ed29fb76..5fa7a9dbcb 100644 --- a/frappe/public/js/frappe/desk.js +++ b/frappe/public/js/frappe/desk.js @@ -148,7 +148,6 @@ frappe.Application = Class.extend({ user: frappe.session.user }, callback: function(r) { - console.log(r); if(r.message.show_alert){ frappe.show_alert({ indicator: 'red', From 8d3894e8a537540899c0412e2a48724014b6c304 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 27 Nov 2020 11:01:49 +0530 Subject: [PATCH 005/187] fix: Validate Python syntax on saves --- frappe/core/doctype/server_script/server_script.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frappe/core/doctype/server_script/server_script.py b/frappe/core/doctype/server_script/server_script.py index 839b784651..ded397d5e3 100644 --- a/frappe/core/doctype/server_script/server_script.py +++ b/frappe/core/doctype/server_script/server_script.py @@ -4,6 +4,8 @@ from __future__ import unicode_literals +import ast + import frappe from frappe.model.document import Document from frappe.utils.safe_exec import safe_exec @@ -11,9 +13,9 @@ from frappe import _ class ServerScript(Document): - @staticmethod - def validate(): + def validate(self): frappe.only_for('Script Manager', True) + ast.parse(self.script) @staticmethod def on_update(): From 5babacac3eac0e4dd2c7734a779b59641b96c94b Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 27 Nov 2020 11:02:37 +0530 Subject: [PATCH 006/187] fix: Show function not available in namespace instead of nothing Prior to this, frappe._dict was being used to inject functions to the server script namespaces. This meant unimplemented methods returned None and we'd get a NoneType not callable error --- frappe/utils/safe_exec.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/frappe/utils/safe_exec.py b/frappe/utils/safe_exec.py index fee6b404ac..50893330be 100644 --- a/frappe/utils/safe_exec.py +++ b/frappe/utils/safe_exec.py @@ -13,7 +13,17 @@ from frappe.www.printview import get_visible_columns import frappe.exceptions import frappe.integrations.utils -class ServerScriptNotEnabled(frappe.PermissionError): pass +class ServerScriptNotEnabled(frappe.PermissionError): + pass + +class NamespaceDict(frappe._dict): + """Raise AttributeError if function not found in namespace""" + def __getattr__(self, key): + ret = self.get(key) + if (not ret and key.startswith("__")) or (key not in self): + raise AttributeError(f"module has no attribute '{key}'") + return ret + def safe_exec(script, _globals=None, _locals=None): # script reports must be enabled via site_config.json @@ -46,13 +56,13 @@ def get_safe_globals(): user = getattr(frappe.local, "session", None) and frappe.local.session.user or "Guest" - out = frappe._dict( + out = NamespaceDict( # make available limited methods of frappe json=json, dict=dict, log=frappe.log, _dict=frappe._dict, - frappe=frappe._dict( + frappe=NamespaceDict( flags=frappe._dict(), format=frappe.format_value, format_value=frappe.format_value, @@ -112,7 +122,7 @@ def get_safe_globals(): out.get_visible_columns = get_visible_columns out.frappe.date_format = date_format out.frappe.time_format = time_format - out.frappe.db = frappe._dict( + out.frappe.db = NamespaceDict( get_list = frappe.get_list, get_all = frappe.get_all, get_value = frappe.db.get_value, From 9808c868d70ce334dadda790ca55b3819d557ca7 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Mon, 30 Nov 2020 14:14:19 +0530 Subject: [PATCH 007/187] feat: allow html in email templates --- .../email_template/email_template.json | 22 +++++++++++++-- .../doctype/email_template/email_template.py | 27 ++++++++++++++++--- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/frappe/email/doctype/email_template/email_template.json b/frappe/email/doctype/email_template/email_template.json index 0d0922f16f..dc73acacc1 100644 --- a/frappe/email/doctype/email_template/email_template.json +++ b/frappe/email/doctype/email_template/email_template.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_import": 1, "allow_rename": 1, "autoname": "Prompt", @@ -8,6 +9,8 @@ "engine": "InnoDB", "field_order": [ "subject", + "use_html", + "response_html", "response", "owner", "section_break_4", @@ -22,11 +25,12 @@ "reqd": 1 }, { + "depends_on": "eval:!doc.use_html", "fieldname": "response", "fieldtype": "Text Editor", "in_list_view": 1, "label": "Response", - "reqd": 1 + "mandatory_depends_on": "eval:!doc.use_html" }, { "default": "user", @@ -45,10 +49,24 @@ "fieldtype": "HTML", "label": "Email Reply Help", "options": "

Email Reply Example

\n\n
Order Overdue\n\nTransaction {{ name }} has exceeded Due Date. Please take necessary action.\n\nDetails\n\n- Customer: {{ customer }}\n- Amount: {{ grand_total }}\n
\n\n

How to get fieldnames

\n\n

The fieldnames you can use in your email template are the fields in the document from which you are sending the email. You can find out the fields of any documents via Setup > Customize Form View and selecting the document type (e.g. Sales Invoice)

\n\n

Templating

\n\n

Templates are compiled using the Jinja Templating Language. To learn more about Jinja, read this documentation.

\n" + }, + { + "default": "0", + "fieldname": "use_html", + "fieldtype": "Check", + "label": "Use HTML" + }, + { + "depends_on": "eval:doc.use_html", + "fieldname": "response_html", + "fieldtype": "Code", + "label": "Response ", + "options": "HTML" } ], "icon": "fa fa-comment", - "modified": "2019-10-30 14:15:00.956347", + "links": [], + "modified": "2020-11-30 14:12:50.321633", "modified_by": "Administrator", "module": "Email", "name": "Email Template", diff --git a/frappe/email/doctype/email_template/email_template.py b/frappe/email/doctype/email_template/email_template.py index 2743032331..6708e9dd3f 100644 --- a/frappe/email/doctype/email_template/email_template.py +++ b/frappe/email/doctype/email_template/email_template.py @@ -9,7 +9,29 @@ from six import string_types class EmailTemplate(Document): def validate(self): - validate_template(self.response) + if self.use_html: + validate_template(self.response_html) + else: + validate_template(self.response) + + def get_formatted_subject(self, doc): + return frappe.render_template(self.subject, doc) + + def get_formatted_response(self, doc): + if self.use_html: + return frappe.render_template(self.response_html, doc) + + return frappe.render_template(self.response, doc) + + def get_formatted_email(self, doc): + if isinstance(doc, string_types): + doc = json.loads(doc) + + return { + "subject" : self.get_formatted_subject(doc), + "message" : self.get_formatted_response(doc) + } + @frappe.whitelist() def get_email_template(template_name, doc): @@ -18,5 +40,4 @@ def get_email_template(template_name, doc): doc = json.loads(doc) email_template = frappe.get_doc("Email Template", template_name) - return {"subject" : frappe.render_template(email_template.subject, doc), - "message" : frappe.render_template(email_template.response, doc)} \ No newline at end of file + return email_template.get_formatted_email(doc) \ No newline at end of file From 4810d07a8a4823a31ceef66b0896a991123ece6e Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Mon, 30 Nov 2020 15:23:12 +0530 Subject: [PATCH 008/187] test: Add tests for throwing AttributeError if method not found --- .../doctype/server_script/test_server_script.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/frappe/core/doctype/server_script/test_server_script.py b/frappe/core/doctype/server_script/test_server_script.py index 3356e584af..256cea57d7 100644 --- a/frappe/core/doctype/server_script/test_server_script.py +++ b/frappe/core/doctype/server_script/test_server_script.py @@ -45,6 +45,15 @@ frappe.response['message'] = 'hello' allow_guest = 1, script = ''' frappe.flags = 'hello' +''' + ), + dict( + name='test_invalid_namespace_method', + script_type = 'DocType Event', + doctype_event = 'Before Insert', + reference_doctype = 'Note', + script = ''' +frappe.method_that_doesnt_exist("do some magic") ''' ) ] @@ -85,3 +94,8 @@ class TestServerScript(unittest.TestCase): def test_api_return(self): self.assertEqual(frappe.get_doc('Server Script', 'test_return_value').execute_method(), 'hello') + + def test_attribute_error(self): + """Raise AttributeError if method not found in Namespace""" + note = frappe.get_doc({"doctype": "Note", "title": "Test Note: Server Script"}) + self.assertRaises(AttributeError, note.insert) From d5d0bc8ea9983438366c059edea0be19a26bf359 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Mon, 30 Nov 2020 15:23:42 +0530 Subject: [PATCH 009/187] fix: Return dummy function to avoid NoneType not callable --- frappe/utils/safe_exec.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/utils/safe_exec.py b/frappe/utils/safe_exec.py index 50893330be..2aacf5eda8 100644 --- a/frappe/utils/safe_exec.py +++ b/frappe/utils/safe_exec.py @@ -21,7 +21,9 @@ class NamespaceDict(frappe._dict): def __getattr__(self, key): ret = self.get(key) if (not ret and key.startswith("__")) or (key not in self): - raise AttributeError(f"module has no attribute '{key}'") + def default_function(*args, **kwargs): + raise AttributeError(f"module has no attribute '{key}'") + return default_function return ret From 3296097df606df2998f01dde927541836504d6bc Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Mon, 30 Nov 2020 15:46:29 +0530 Subject: [PATCH 010/187] feat: show absolute value in print format --- frappe/model/base_document.py | 6 +++--- frappe/printing/doctype/print_format/print_format.json | 9 ++++++++- frappe/templates/print_formats/standard_macros.html | 5 ++--- frappe/www/printview.py | 1 + 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index 0a219b4253..5d86b3bac8 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -802,12 +802,12 @@ class BaseDocument(object): if translated: val = _(val) - if absolute_value and isinstance(val, (int, float)): - val = abs(self.get(fieldname)) - if not doc: doc = getattr(self, "parent_doc", None) or self + if (absolute_value or doc.get('absolute_value')) and isinstance(val, (int, float)): + val = abs(self.get(fieldname)) + return format_value(val, df=df, doc=doc, currency=currency) def is_print_hide(self, fieldname, df=None, for_print=True): diff --git a/frappe/printing/doctype/print_format/print_format.json b/frappe/printing/doctype/print_format/print_format.json index 63448ccc39..3867ce4502 100644 --- a/frappe/printing/doctype/print_format/print_format.json +++ b/frappe/printing/doctype/print_format/print_format.json @@ -22,6 +22,7 @@ "align_labels_right", "show_section_headings", "line_breaks", + "absolute_value", "column_break_11", "font", "css_section", @@ -196,13 +197,19 @@ "fieldtype": "Check", "hidden": 1, "label": "Print Format Builder" + }, + { + "default": "0", + "fieldname": "absolute_value", + "fieldtype": "Check", + "label": "Show absolute values" } ], "icon": "fa fa-print", "idx": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2020-10-27 18:27:58.307070", + "modified": "2020-11-30 15:26:35.605213", "modified_by": "Administrator", "module": "Printing", "name": "Print Format", diff --git a/frappe/templates/print_formats/standard_macros.html b/frappe/templates/print_formats/standard_macros.html index 3681a87f53..168547798b 100644 --- a/frappe/templates/print_formats/standard_macros.html +++ b/frappe/templates/print_formats/standard_macros.html @@ -136,10 +136,9 @@ data-fieldname="{{ df.fieldname }}" data-fieldtype="{{ df.fieldtype }}" {%- if df.print_width %} style="width: {{ get_width(df) }};"{% endif %}> {% elif df.fieldtype=="HTML" %} {{ frappe.render_template(df.options, {"doc":doc}) }} - {% elif df.fieldtype=="Currency" %} - {{ doc.get_formatted(df.fieldname, doc, translated=df.translatable) }} {% else %} - {{ doc.get_formatted(df.fieldname, parent_doc or doc, translated=df.translatable) }} + {%- set parent = parent_doc or doc -%} + {{ doc.get_formatted(df.fieldname, parent, translated=df.translatable, absolute_value=parent.absolute_value) }} {% endif %} {%- endmacro %} diff --git a/frappe/www/printview.py b/frappe/www/printview.py index 545e5d581d..71316dc48c 100644 --- a/frappe/www/printview.py +++ b/frappe/www/printview.py @@ -100,6 +100,7 @@ def get_rendered_template(doc, name=None, print_format=None, meta=None, doc.print_section_headings = print_format.show_section_headings doc.print_line_breaks = print_format.line_breaks doc.align_labels_right = print_format.align_labels_right + doc.absolute_value = print_format.absolute_value def get_template_from_string(): return jenv.from_string(get_print_format(doc.doctype, From aadbdfbd84482a37ab8503a5cc5a868019138346 Mon Sep 17 00:00:00 2001 From: Anuja Pawar <60467153+Anuja-pawar@users.noreply.github.com> Date: Wed, 2 Dec 2020 17:51:38 +0530 Subject: [PATCH 011/187] refactor(System Settings): Remove redundant code (#12027) Co-authored-by: Anuja --- .../system_settings/system_settings.js | 63 +++++++++---------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/frappe/core/doctype/system_settings/system_settings.js b/frappe/core/doctype/system_settings/system_settings.js index b6514dea9f..c0c9074cbc 100644 --- a/frappe/core/doctype/system_settings/system_settings.js +++ b/frappe/core/doctype/system_settings/system_settings.js @@ -1,37 +1,36 @@ -frappe.ui.form.on("System Settings", "refresh", function(frm) { - frappe.call({ - method: "frappe.core.doctype.system_settings.system_settings.load", - callback: function(data) { - frappe.all_timezones = data.message.timezones; - frm.set_df_property("time_zone", "options", frappe.all_timezones); +frappe.ui.form.on("System Settings", { + refresh: function(frm) { + frappe.call({ + method: "frappe.core.doctype.system_settings.system_settings.load", + callback: function(data) { + frappe.all_timezones = data.message.timezones; + frm.set_df_property("time_zone", "options", frappe.all_timezones); - $.each(data.message.defaults, function(key, val) { - frm.set_value(key, val); - frappe.sys_defaults[key] = val; - }) + $.each(data.message.defaults, function(key, val) { + frm.set_value(key, val); + frappe.sys_defaults[key] = val; + }); + } + }); + }, + enable_password_policy: function(frm) { + if (frm.doc.enable_password_policy == 0) { + frm.set_value("minimum_password_score", ""); + } else { + frm.set_value("minimum_password_score", "2"); } - }); -}); - -frappe.ui.form.on("System Settings", "enable_password_policy", function(frm) { - if(frm.doc.enable_password_policy == 0){ - frm.set_value("minimum_password_score", ""); - } else { - frm.set_value("minimum_password_score", "2"); - } -}); - -frappe.ui.form.on("System Settings", "enable_two_factor_auth", function(frm) { - if(frm.doc.enable_two_factor_auth == 0){ - frm.set_value("bypass_2fa_for_retricted_ip_users", 0); - frm.set_value("bypass_restrict_ip_check_if_2fa_enabled", 0); - } -}); - -frappe.ui.form.on("System Settings", "enable_prepared_report_auto_deletion", function(frm) { - if (frm.doc.enable_prepared_report_auto_deletion) { - if (!frm.doc.prepared_report_expiry_period) { - frm.set_value('prepared_report_expiry_period', 7); + }, + enable_two_factor_auth: function(frm) { + if (frm.doc.enable_two_factor_auth == 0) { + frm.set_value("bypass_2fa_for_retricted_ip_users", 0); + frm.set_value("bypass_restrict_ip_check_if_2fa_enabled", 0); + } + }, + enable_prepared_report_auto_deletion: function(frm) { + if (frm.doc.enable_prepared_report_auto_deletion) { + if (!frm.doc.prepared_report_expiry_period) { + frm.set_value('prepared_report_expiry_period', 7); + } } } }); From a19932835a8e8ab66042e19c8ae52f87a19af946 Mon Sep 17 00:00:00 2001 From: Anupam Date: Thu, 3 Dec 2020 12:30:10 +0530 Subject: [PATCH 012/187] feat: provision to open child table in customize form --- frappe/custom/doctype/customize_form/customize_form.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frappe/custom/doctype/customize_form/customize_form.js b/frappe/custom/doctype/customize_form/customize_form.js index 2d220b864c..17343573ed 100644 --- a/frappe/custom/doctype/customize_form/customize_form.js +++ b/frappe/custom/doctype/customize_form/customize_form.js @@ -81,6 +81,11 @@ frappe.ui.form.on("Customize Form", { } else { f._sortable = false; } + if (f.fieldtype == "Table") { + frm.add_custom_button(f.options, function() { + frm.set_value('doc_type', f.options); + }, __('Customize Child Table')); + } }); frm.fields_dict.fields.grid.refresh(); }, From 6c48c2d14aa81d9ed2dc0545f45cda6672e41cef Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Date: Thu, 3 Dec 2020 14:10:47 +0530 Subject: [PATCH 013/187] fix(charts): escape nan in each y axis --- frappe/public/js/frappe/views/reports/report_utils.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/views/reports/report_utils.js b/frappe/public/js/frappe/views/reports/report_utils.js index 158dbd653b..ebb08bd24b 100644 --- a/frappe/public/js/frappe/views/reports/report_utils.js +++ b/frappe/public/js/frappe/views/reports/report_utils.js @@ -15,7 +15,9 @@ frappe.report_utils = { if (raw_data.add_total_row) { labels = labels.slice(0, -1); - datasets[0].values = datasets[0].values.slice(0, -1); + datasets.forEach(dataset => { + dataset.values = dataset.values.slice(0, -1); + }); } return { From ee3fa3e4e0ebf414a9a7e777a509f6a7535be0a0 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Thu, 3 Dec 2020 22:39:38 +0530 Subject: [PATCH 014/187] fix: Remove unreferenced variable base_path --- frappe/commands/site.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/frappe/commands/site.py b/frappe/commands/site.py index bc65aa178c..35f5b13582 100755 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -100,12 +100,10 @@ def restore(context, sql_file_path, mariadb_root_username=None, mariadb_root_pas # Extract public and/or private files to the restored site, if user has given the path if with_public_files: - with_public_files = os.path.join(base_path, with_public_files) public = extract_files(site, with_public_files, 'public') os.remove(public) if with_private_files: - with_private_files = os.path.join(base_path, with_private_files) private = extract_files(site, with_private_files, 'private') os.remove(private) From 9ac14fb5abf6930234e4da41217dd74718c858da Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Thu, 3 Dec 2020 23:26:34 +0530 Subject: [PATCH 015/187] feat: Permission Query script type Add dynamic conditions in where clause of get_list query --- .../doctype/server_script/server_script.js | 41 ++++++++++++++----- .../doctype/server_script/server_script.json | 6 +-- .../doctype/server_script/server_script.py | 6 +++ .../server_script/server_script_utils.py | 11 ++++- .../server_script/test_server_script.py | 12 ++++++ frappe/model/db_query.py | 13 +++++- 6 files changed, 71 insertions(+), 18 deletions(-) diff --git a/frappe/core/doctype/server_script/server_script.js b/frappe/core/doctype/server_script/server_script.js index 78ef2d0509..a317d69166 100644 --- a/frappe/core/doctype/server_script/server_script.js +++ b/frappe/core/doctype/server_script/server_script.js @@ -48,29 +48,33 @@ frappe.ui.form.on('Server Script', { setup_help(frm) { frm.get_field('help_html').html(` -

Examples

DocType Event

-

+

Add logic for standard doctype events like Before Insert, After Submit, etc.

+
+	
 # set property
 if "test" in doc.description:
-    doc.status = 'Closed'
+	doc.status = 'Closed'
 
 
 # validate
 if "validate" in doc.description:
-    raise frappe.ValidationError
+	raise frappe.ValidationError
 
 # auto create another document
-if doc.allocted_to:
-    frappe.get_doc(dict(
-        doctype = 'ToDo'
-        owner = doc.allocated_to,
-        description = doc.subject
-    )).insert()
-
+if doc.allocated_to: + frappe.get_doc(dict( + doctype = 'ToDo' + owner = doc.allocated_to, + description = doc.subject + )).insert() +
+
+

API Call

+

Respond to /api/method/<method-name> calls, just like whitelisted methods


 # respond to API
 
@@ -79,6 +83,21 @@ if frappe.form_dict.message == "ping":
 else:
 	frappe.response['message'] = "ok"
 
+ +
+ +

Permission Query

+

Add conditions to the where clause of list queries.

+

+# generate dynamic conditions and set it in the conditions variable
+tenant_id = frappe.db.get_value(...)
+conditions = 'tenant_id = {}'.format(tenant_id)
+
+# resulting select query
+select name from \`tabPerson\`
+where tenant_id = 2
+order by creation desc
+
`); } diff --git a/frappe/core/doctype/server_script/server_script.json b/frappe/core/doctype/server_script/server_script.json index 420f96ec2f..94a48f196c 100644 --- a/frappe/core/doctype/server_script/server_script.json +++ b/frappe/core/doctype/server_script/server_script.json @@ -24,7 +24,7 @@ "fieldtype": "Select", "in_list_view": 1, "label": "Script Type", - "options": "DocType Event\nScheduler Event\nAPI", + "options": "DocType Event\nScheduler Event\nPermission Query\nAPI", "reqd": 1 }, { @@ -35,7 +35,7 @@ "reqd": 1 }, { - "depends_on": "eval:doc.script_type==='DocType Event'", + "depends_on": "eval:['DocType Event', 'Permission Query'].includes(doc.script_type)", "fieldname": "reference_doctype", "fieldtype": "Link", "in_list_view": 1, @@ -88,7 +88,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2020-11-11 12:39:41.391052", + "modified": "2020-12-03 22:42:02.708148", "modified_by": "Administrator", "module": "Core", "name": "Server Script", diff --git a/frappe/core/doctype/server_script/server_script.py b/frappe/core/doctype/server_script/server_script.py index 839b784651..b1bf79dc52 100644 --- a/frappe/core/doctype/server_script/server_script.py +++ b/frappe/core/doctype/server_script/server_script.py @@ -41,6 +41,12 @@ class ServerScript(Document): # wrong report type! raise frappe.DoesNotExistError + def get_permission_query_conditions(self, user): + locals = {"user": user, "conditions": ""} + safe_exec(self.script, None, locals) + if locals["conditions"]: + return locals["conditions"] + @frappe.whitelist() def setup_scheduler_events(script_name, frequency): method = frappe.scrub('{0}-{1}'.format(script_name, frequency)) diff --git a/frappe/core/doctype/server_script/server_script_utils.py b/frappe/core/doctype/server_script/server_script_utils.py index e03504f30b..4dc4f12b34 100644 --- a/frappe/core/doctype/server_script/server_script_utils.py +++ b/frappe/core/doctype/server_script/server_script_utils.py @@ -50,6 +50,9 @@ def get_server_script_map(): # }, # '_api': { # '[path]': '[server script]' + # }, + # 'permission_query': { + # 'DocType': '[server script]' # } # } if frappe.flags.in_patch and not frappe.db.table_exists('Server Script'): @@ -57,16 +60,20 @@ def get_server_script_map(): script_map = frappe.cache().get_value('server_script_map') if script_map is None: - script_map = {} + script_map = { + 'permission_query': {} + } enabled_server_scripts = frappe.get_all('Server Script', fields=('name', 'reference_doctype', 'doctype_event','api_method', 'script_type'), filters={'disabled': 0}) for script in enabled_server_scripts: if script.script_type == 'DocType Event': script_map.setdefault(script.reference_doctype, {}).setdefault(script.doctype_event, []).append(script.name) + elif script.script_type == 'Permission Query': + script_map['permission_query'][script.reference_doctype] = script.name else: script_map.setdefault('_api', {})[script.api_method] = script.name frappe.cache().set_value('server_script_map', script_map) - return script_map \ No newline at end of file + return script_map diff --git a/frappe/core/doctype/server_script/test_server_script.py b/frappe/core/doctype/server_script/test_server_script.py index 3356e584af..565436d9f2 100644 --- a/frappe/core/doctype/server_script/test_server_script.py +++ b/frappe/core/doctype/server_script/test_server_script.py @@ -45,6 +45,14 @@ frappe.response['message'] = 'hello' allow_guest = 1, script = ''' frappe.flags = 'hello' +''' + ), + dict( + name='test_permission_query', + script_type = 'Permission Query', + reference_doctype = 'ToDo', + script = ''' +conditions = '1 = 1' ''' ) ] @@ -85,3 +93,7 @@ class TestServerScript(unittest.TestCase): def test_api_return(self): self.assertEqual(frappe.get_doc('Server Script', 'test_return_value').execute_method(), 'hello') + + def test_permission_query(self): + self.assertTrue('where (1 = 1)' in frappe.db.get_list('ToDo', return_query=1)) + self.assertTrue(isinstance(frappe.db.get_list('ToDo'), list)) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index ace9b04cec..b936251b50 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -18,6 +18,7 @@ from frappe.client import check_parent_permission from frappe.model.utils.user_settings import get_user_settings, update_user_settings from frappe.utils import flt, cint, get_time, make_filter_tuple, get_filter, add_to_date, cstr, get_timespan_date_range from frappe.model.meta import get_table_columns +from frappe.core.doctype.server_script.server_script_utils import get_server_script_map class DatabaseQuery(object): def __init__(self, doctype, user=None): @@ -683,15 +684,23 @@ class DatabaseQuery(object): self.match_filters.append(match_filters) def get_permission_query_conditions(self): + conditions = [] condition_methods = frappe.get_hooks("permission_query_conditions", {}).get(self.doctype, []) if condition_methods: - conditions = [] for method in condition_methods: c = frappe.call(frappe.get_attr(method), self.user) if c: conditions.append(c) - return " and ".join(conditions) if conditions else None + permision_script_name = get_server_script_map().get("permission_query").get(self.doctype) + if permision_script_name: + script = frappe.get_doc("Server Script", permision_script_name) + condition = script.get_permission_query_conditions(self.user) + if condition: + conditions.append(condition) + + return " and ".join(conditions) if conditions else "" + def run_custom_query(self, query): if '%(key)s' in query: From e338f2f7b6cb5e446dacd9a7527d12e1c4806405 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Thu, 3 Dec 2020 23:56:26 +0530 Subject: [PATCH 016/187] fix(newsletter): Render template for HTML content type --- frappe/email/doctype/newsletter/newsletter.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py index a4d60706eb..2791ebb75b 100755 --- a/frappe/email/doctype/newsletter/newsletter.py +++ b/frappe/email/doctype/newsletter/newsletter.py @@ -85,11 +85,11 @@ class Newsletter(WebsiteGenerator): self.db_set("scheduled_to_send", len(self.recipients)) def get_message(self): - + if self.content_type == "HTML": + return frappe.render_template(self.message_html, {"doc": self.as_dict()}) return { 'Rich Text': self.message, - 'Markdown': markdown(self.message_md), - 'HTML': self.message_html + 'Markdown': markdown(self.message_md) }[self.content_type or 'Rich Text'] def get_recipients(self): From 6328103cfacd0170bdb59432e2b2f134ac941df6 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 4 Dec 2020 14:15:29 +0530 Subject: [PATCH 017/187] fix: Timeline style --- .../js/frappe/form/footer/form_timeline.js | 4 +-- frappe/public/scss/desk/timeline.scss | 34 +++++++++++-------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/frappe/public/js/frappe/form/footer/form_timeline.js b/frappe/public/js/frappe/form/footer/form_timeline.js index b632379f44..f1966a466d 100644 --- a/frappe/public/js/frappe/form/footer/form_timeline.js +++ b/frappe/public/js/frappe/form/footer/form_timeline.js @@ -47,7 +47,7 @@ class FormTimeline extends BaseTimeline {

${__('Activity')}

-
diff --git a/frappe/public/scss/desk/avatar.scss b/frappe/public/scss/desk/avatar.scss index c139cdb146..1c1bd9549f 100644 --- a/frappe/public/scss/desk/avatar.scss +++ b/frappe/public/scss/desk/avatar.scss @@ -158,6 +158,7 @@ display: inline-flex; align-items: center; flex-direction: row-reverse; + cursor: pointer; &.right { justify-content: flex-start; diff --git a/frappe/public/scss/desk/modal.scss b/frappe/public/scss/desk/modal.scss index 4ac26d34e7..e6e01c533c 100644 --- a/frappe/public/scss/desk/modal.scss +++ b/frappe/public/scss/desk/modal.scss @@ -74,17 +74,6 @@ h5.modal-title { } } - @include media-breakpoint-up(md) { - .modal-dialog { - width: 575px; - max-width: 575px; - &.modal-lg { - width: 800px; - max-width: unquote("min(80vw, 800px)") - } - } - } - .form-section { padding: var(--padding-sm) 0; @@ -183,4 +172,26 @@ h5.modal-title { } } } +} + +.dialog-assignment-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 5px 15px; + border-radius: var(--border-radius-md); + margin-bottom: 5px; + @extend .row; + .remove-btn { + display: none; + } + &:hover { + background: var(--gray-100); + .remove-btn { + display: block; + } + } + .avatar { + margin-right: var(--margin-md); + } } \ No newline at end of file diff --git a/frappe/public/scss/desk/navbar.scss b/frappe/public/scss/desk/navbar.scss index b0fc59eff2..be21412dac 100644 --- a/frappe/public/scss/desk/navbar.scss +++ b/frappe/public/scss/desk/navbar.scss @@ -15,7 +15,7 @@ padding: 0 1rem; } .vertical-bar { - border-right: 1px solid var(--gray-200); + border-right: 1px solid var(--dark-border-color); height: 24px; margin: auto; margin-left: var(--margin-md); diff --git a/frappe/public/scss/desk/variables.scss b/frappe/public/scss/desk/variables.scss index 86623d2a9c..9db007508d 100644 --- a/frappe/public/scss/desk/variables.scss +++ b/frappe/public/scss/desk/variables.scss @@ -55,6 +55,8 @@ $component-active-bg: $gray-600; $modal-content-bg: var(--modal-bg); $modal-backdrop-bg: var(--gray-900); $modal-content-box-shadow-sm-up: 0px 5px 10px rgba(0, 0, 0, 0.100661); +$modal-md: 575px; +$modal-sm: 450px; $link-color: var(--text-color); // input From 287fb8a8e5242271e9ac8c2e2598522ca6d60ef6 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 8 Dec 2020 17:06:11 +0530 Subject: [PATCH 082/187] fix: Make assign and share button round --- frappe/public/scss/desk/sidebar.scss | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/frappe/public/scss/desk/sidebar.scss b/frappe/public/scss/desk/sidebar.scss index aaba3da5c7..ebbdcd8151 100644 --- a/frappe/public/scss/desk/sidebar.scss +++ b/frappe/public/scss/desk/sidebar.scss @@ -417,11 +417,6 @@ body[data-route^="Module"] .main-menu { display: inline-flex; } -.reviews { - display: flex; - flex-wrap: wrap; -} - button.data-pill { .icon { margin-left: var(--margin-xs); @@ -440,14 +435,17 @@ button.data-pill { .add-attachment-btn, .shares, -.share-doc-btn, -.followed-by, -.add-review-btn, -.add-assignment-btn { +.followed-by { max-width: 100%; display: block; } +.add-review-btn, +.share-doc-btn, +.add-assignment-btn { + border-radius: 50%; +} + .form-reviews { .reviews { display: flex; From e197a6fd7fbecfca9eadd8c2d92577eb20ba12b7 Mon Sep 17 00:00:00 2001 From: Anupam Date: Tue, 8 Dec 2020 11:35:41 +0530 Subject: [PATCH 083/187] feat: added data format support DD-Mon-YY --- frappe/public/js/frappe/data_import/import_preview.js | 1 + frappe/utils/data.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/frappe/public/js/frappe/data_import/import_preview.js b/frappe/public/js/frappe/data_import/import_preview.js index 6c17cb4351..477cfb0786 100644 --- a/frappe/public/js/frappe/data_import/import_preview.js +++ b/frappe/public/js/frappe/data_import/import_preview.js @@ -101,6 +101,7 @@ frappe.data_import.ImportPreview = class ImportPreview { .replace('%H', 'HH') .replace('%M', 'mm') .replace('%S', 'ss') + .replace('%b', 'Mon') : null; let column_title = ` diff --git a/frappe/utils/data.py b/frappe/utils/data.py index 41f247da45..cef4243913 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -1300,12 +1300,14 @@ def generate_hash(*args, **kwargs): def guess_date_format(date_string): DATE_FORMATS = [ + r"%d/%b/%y", r"%d-%m-%Y", r"%m-%d-%Y", r"%Y-%m-%d", r"%d-%m-%y", r"%m-%d-%y", r"%y-%m-%d", + r"%y-%b-%d", r"%d/%m/%Y", r"%m/%d/%Y", r"%Y/%m/%d", From 9cb199de302895e333737157d35609327bbbc010 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 8 Dec 2020 17:22:23 +0530 Subject: [PATCH 084/187] fix: Replace fa icon for close with svg icon --- .../frappe/form/controls/multiselect_pills.js | 2 +- .../frappe/form/controls/table_multiselect.js | 2 +- frappe/public/js/frappe/ui/filters/filter.js | 2 +- frappe/public/less/common.less | 27 ------------------- frappe/public/scss/desk/modal.scss | 2 -- 5 files changed, 3 insertions(+), 32 deletions(-) diff --git a/frappe/public/js/frappe/form/controls/multiselect_pills.js b/frappe/public/js/frappe/form/controls/multiselect_pills.js index 6190204357..e73810c4dc 100644 --- a/frappe/public/js/frappe/form/controls/multiselect_pills.js +++ b/frappe/public/js/frappe/form/controls/multiselect_pills.js @@ -87,7 +87,7 @@ frappe.ui.form.ControlMultiSelectPills = frappe.ui.form.ControlAutocomplete.exte return `
`; }, diff --git a/frappe/public/js/frappe/form/controls/table_multiselect.js b/frappe/public/js/frappe/form/controls/table_multiselect.js index 1d85498b80..10e22eacb6 100644 --- a/frappe/public/js/frappe/form/controls/table_multiselect.js +++ b/frappe/public/js/frappe/form/controls/table_multiselect.js @@ -126,7 +126,7 @@ frappe.ui.form.ControlTableMultiSelect = frappe.ui.form.ControlLink.extend({ return `
`; }, diff --git a/frappe/public/js/frappe/ui/filters/filter.js b/frappe/public/js/frappe/ui/filters/filter.js index 606d01292a..9ad88e0fcd 100644 --- a/frappe/public/js/frappe/ui/filters/filter.js +++ b/frappe/public/js/frappe/ui/filters/filter.js @@ -365,7 +365,7 @@ frappe.ui.Filter = class { `); } diff --git a/frappe/public/less/common.less b/frappe/public/less/common.less index 0e9f310062..23a4739d54 100644 --- a/frappe/public/less/common.less +++ b/frappe/public/less/common.less @@ -117,33 +117,6 @@ a.badge-hover& { } } -// .msgprint-dialog { -// max-width: 400px; - -// .modal-content { -// min-height: 110px; -// } -// } - -// .msgprint-scroll { -// max-height: 36em; -// overflow: scroll; -// } - -// .msgprint { -// // margin: 15px 0px; -// // text-align: center; -// word-wrap: break-word; - -// pre { -// text-align: left; -// } - -// a:not(.btn) { -// text-decoration: underline; -// } -// } - .centered { position: absolute; top: 50%; diff --git a/frappe/public/scss/desk/modal.scss b/frappe/public/scss/desk/modal.scss index e6e01c533c..44148787b5 100644 --- a/frappe/public/scss/desk/modal.scss +++ b/frappe/public/scss/desk/modal.scss @@ -135,8 +135,6 @@ h5.modal-title { /* msgprint dialog */ .msgprint-dialog { - max-width: 400px; - .modal-content { min-height: 110px; } From 62b4ee5d2fe9e9c04127445b730c5ba4fae0c2b6 Mon Sep 17 00:00:00 2001 From: prssanna Date: Tue, 8 Dec 2020 18:13:03 +0530 Subject: [PATCH 085/187] fix: kanban assignment button --- frappe/public/js/frappe/views/kanban/kanban_board.js | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/public/js/frappe/views/kanban/kanban_board.js b/frappe/public/js/frappe/views/kanban/kanban_board.js index 601778c65d..997f29417c 100644 --- a/frappe/public/js/frappe/views/kanban/kanban_board.js +++ b/frappe/public/js/frappe/views/kanban/kanban_board.js @@ -597,6 +597,7 @@ frappe.provide("frappe.views"); function show_assign_to_dialog(e) { e.preventDefault(); + e.stopPropagation(); self.assign_to = new frappe.ui.form.AssignToDialog({ obj: self, method: 'frappe.desk.form.assign_to.add', From 2e05b79d71f56c8e1f72ba2f58a1d541bd4b44ec Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 8 Dec 2020 19:51:27 +0530 Subject: [PATCH 086/187] fix: Avatar group style - Match style in the mockup --- frappe/public/js/frappe/utils/common.js | 31 ++++++++++++++----------- frappe/public/scss/desk/avatar.scss | 16 +++++-------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/frappe/public/js/frappe/utils/common.js b/frappe/public/js/frappe/utils/common.js index fa677dffa5..47345537d4 100644 --- a/frappe/public/js/frappe/utils/common.js +++ b/frappe/public/js/frappe/utils/common.js @@ -1,6 +1,6 @@ // common file between desk and website -frappe.avatar = function (user, css_class, title, image_url = null, remove_color=false, filterable=false) { +frappe.avatar = function (user, css_class, title, image_url=null, remove_color=false, filterable=false) { let user_info; if (user) { // desk @@ -21,11 +21,11 @@ frappe.avatar = function (user, css_class, title, image_url = null, remove_color } return frappe.get_avatar( - user, css_class, title, image_url || user_info.image, remove_color=remove_color, filterable=filterable + user, css_class, title, image_url || user_info.image, remove_color, filterable ); }; -frappe.get_avatar = function(user, css_class, title, image_url = null, remove_color, filterable) { +frappe.get_avatar = function(user, css_class, title, image_url=null, remove_color, filterable) { let data_attr = ''; if (!css_class) { @@ -64,40 +64,43 @@ frappe.get_avatar = function(user, css_class, title, image_url = null, remove_co } } -frappe.avatar_group = function (users, limit = 4, options = {}) { - let icon_html = ''; +frappe.avatar_group = function (users, limit=4, options = {}) { + let avatar_action_html = ''; const display_users = users.slice(0, limit); const extra_users = users.slice(limit); + const css_class = options.css_class || ''; let html = display_users.map(user => - frappe.avatar(user, 'avatar-small ' + options.css_class, null, null, false, options.filterable) + frappe.avatar(user, 'avatar-small ' + css_class, null, null, false, options.filterable) ).join(''); if (extra_users.length === 1) { - html += frappe.avatar(extra_users[0], 'avatar-small ' + options.css_class, null, null, false, options.filterable); + html += frappe.avatar(extra_users[0], 'avatar-small ' + css_class, null, null, false, options.filterable); } else if (extra_users.length > 1) { html = ` - + ${html} +
+${extra_users.length}
- ${html} `; } if (options.action_icon) { - icon_html = ` -
+ avatar_action_html = ` + +
${frappe.utils.icon(options.action_icon, 'sm')} -
-
`; +
+
+ `; } const $avatar_group = $(`
- ${icon_html} ${html} + ${avatar_action_html}
`); $avatar_group.find('.avatar-action').on('click', options.action); diff --git a/frappe/public/scss/desk/avatar.scss b/frappe/public/scss/desk/avatar.scss index 1c1bd9549f..d6fa548202 100644 --- a/frappe/public/scss/desk/avatar.scss +++ b/frappe/public/scss/desk/avatar.scss @@ -1,7 +1,7 @@ :root { --avatar-frame-color: var(--gray-500); --avatar-frame-bg: var(--gray-100); - --avatar-frame-border: var(--gray-100); + --avatar-frame-border: var(--gray-50); --orange-avatar-bg: var(--orange-100); --orange-avatar-color: var(--orange-600); @@ -157,7 +157,6 @@ .avatar-group { display: inline-flex; align-items: center; - flex-direction: row-reverse; cursor: pointer; &.right { @@ -168,12 +167,13 @@ } .avatar-action { - width: 100%; - height: 100%; + @extend .avatar-small; display: flex; justify-content: center; align-items: center; background-color: var(--control-bg); + border-radius: 50%; + cursor: pointer !important; .icon { use { @@ -187,10 +187,6 @@ .avatar-frame { border: 1px solid var(--avatar-frame-border); } - - &:not(.avatar-extra-count):hover { - z-index: 99; - } } .avatar-extra-count { @@ -200,13 +196,13 @@ background-color: var(--blue-500); } - .avatar { + .avatar:last-child { margin-right: var(--margin-xs); } &.overlap { .avatar + .avatar { - margin-right: calc(-1 * var(--margin-sm)); + margin-left: calc(-1 * var(--margin-sm)); } } } From b1f78356724d1014994e184564d575face292919 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 8 Dec 2020 20:07:19 +0530 Subject: [PATCH 087/187] style: Use snake_case for variable --- frappe/public/js/frappe/views/kanban/kanban_board.js | 5 +++-- frappe/public/scss/desk/kanban.scss | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/frappe/public/js/frappe/views/kanban/kanban_board.js b/frappe/public/js/frappe/views/kanban/kanban_board.js index 997f29417c..a6187459c0 100644 --- a/frappe/public/js/frappe/views/kanban/kanban_board.js +++ b/frappe/public/js/frappe/views/kanban/kanban_board.js @@ -583,8 +583,9 @@ frappe.provide("frappe.views"); } function add_task_link() { - let taskLink = frappe.utils.get_form_link(card.doctype, card.name); - self.$card.find('.kanban-card-redirect').attr('href', taskLink); + let task_link = frappe.utils.get_form_link(card.doctype, card.name); + self.$card.find('.kanban-card-redirect') + .attr('href', task_link); } function get_assignees_group() { diff --git a/frappe/public/scss/desk/kanban.scss b/frappe/public/scss/desk/kanban.scss index 696270909a..848ca91d47 100644 --- a/frappe/public/scss/desk/kanban.scss +++ b/frappe/public/scss/desk/kanban.scss @@ -155,7 +155,7 @@ @include flex(flex, space-between, null, column); @include card( - $padding: 10px 15px, + $padding: var(--padding-sm) var(--padding-md), $background-color: var(--kanban-card-bg) ); margin-top: var(--margin-sm); From 62e6643ef8ccacd6d9cc5c224b5b3165e7582f26 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 8 Dec 2020 20:07:44 +0530 Subject: [PATCH 088/187] fix: Avatar group margin --- frappe/public/scss/desk/avatar.scss | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/frappe/public/scss/desk/avatar.scss b/frappe/public/scss/desk/avatar.scss index d6fa548202..cc8c16ce44 100644 --- a/frappe/public/scss/desk/avatar.scss +++ b/frappe/public/scss/desk/avatar.scss @@ -161,18 +161,20 @@ &.right { justify-content: flex-start; + margin-left: var(--margin-xs); } &.left { justify-content: flex-end; + margin-right: var(--margin-xs); } + .avatar-action { @extend .avatar-small; display: flex; justify-content: center; align-items: center; background-color: var(--control-bg); - border-radius: 50%; cursor: pointer !important; .icon { @@ -196,10 +198,6 @@ background-color: var(--blue-500); } - .avatar:last-child { - margin-right: var(--margin-xs); - } - &.overlap { .avatar + .avatar { margin-left: calc(-1 * var(--margin-sm)); From ccad7473fd7b93c3df623579211b334391aea136 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 8 Dec 2020 20:15:58 +0530 Subject: [PATCH 089/187] fix: Workspace sidebar toggle --- frappe/public/js/frappe/views/workspace/workspace.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/frappe/public/js/frappe/views/workspace/workspace.js b/frappe/public/js/frappe/views/workspace/workspace.js index 8c2a041386..ebd3fbee3a 100644 --- a/frappe/public/js/frappe/views/workspace/workspace.js +++ b/frappe/public/js/frappe/views/workspace/workspace.js @@ -203,16 +203,9 @@ frappe.views.Workspace = class Workspace { show_or_hide_sidebar() { let show_workspace_sidebar = JSON.parse(localStorage.show_workspace_sidebar || "true"); - $('#page-workspace .layout-main-section-wrapper').toggleClass("col-md-12", !show_workspace_sidebar); - $('#page-workspace .layout-main-section-wrapper').toggleClass("col-lg-12", !show_workspace_sidebar); $('#page-workspace .layout-side-section').toggleClass('hidden', !show_workspace_sidebar); - - $('#page-workspace .layout-main-section-wrapper').toggleClass("col-md-10", show_workspace_sidebar); - $('#page-workspace .layout-main-section-wrapper').toggleClass("col-lg-10", show_workspace_sidebar); - - // $(document.body).toggleClass("no-sidebar", !show_desk_sidebar); } -} +}; class DesktopPage { constructor({ container, page_name }) { From 9dcb12d7592358b638f8e121e0a48ab569cdf0d0 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 8 Dec 2020 20:47:43 +0530 Subject: [PATCH 090/187] fix: Assignment hover color - Other style fixes --- frappe/public/js/frappe/form/sidebar/assign_to.js | 1 + frappe/public/scss/desk/modal.scss | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/form/sidebar/assign_to.js b/frappe/public/js/frappe/form/sidebar/assign_to.js index 90649f5208..f8461d1fdf 100644 --- a/frappe/public/js/frappe/form/sidebar/assign_to.js +++ b/frappe/public/js/frappe/form/sidebar/assign_to.js @@ -246,6 +246,7 @@ frappe.ui.form.AssignmentDialog = class { }); this.assignment_list = $(this.dialog.get_field('assignment_list').wrapper); + this.assignment_list.removeClass('frappe-control'); this.assignments.forEach(assignment => { this.update_assignment(assignment); diff --git a/frappe/public/scss/desk/modal.scss b/frappe/public/scss/desk/modal.scss index 44148787b5..7106844ef8 100644 --- a/frappe/public/scss/desk/modal.scss +++ b/frappe/public/scss/desk/modal.scss @@ -178,13 +178,16 @@ h5.modal-title { justify-content: space-between; padding: 5px 15px; border-radius: var(--border-radius-md); - margin-bottom: 5px; + color: var(--text-color); + &:not(:last-child) { + margin-bottom: 5px; + } @extend .row; .remove-btn { display: none; } &:hover { - background: var(--gray-100); + background: var(--fg-hover-color); .remove-btn { display: block; } From 68fcbc7684ceba79b9fa7c8be65d11fc5e037ad0 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 9 Dec 2020 10:21:27 +0530 Subject: [PATCH 091/187] fix: Timeline sequence --- frappe/public/js/frappe/form/footer/base_timeline.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/form/footer/base_timeline.js b/frappe/public/js/frappe/form/footer/base_timeline.js index 0e983cb66b..fa429f52d4 100644 --- a/frappe/public/js/frappe/form/footer/base_timeline.js +++ b/frappe/public/js/frappe/form/footer/base_timeline.js @@ -43,11 +43,11 @@ class BaseTimeline { let response = this.prepare_timeline_contents(); if (response instanceof Promise) { response.then(() => { - this.timeline_items.sort((item1, item2) => new Date(item1.creation) - new Date(item2.creation)); + this.timeline_items.sort((item1, item2) => new Date(item2.creation) - new Date(item1.creation)); this.timeline_items.forEach(this.add_timeline_item.bind(this)); }); } else { - this.timeline_items.sort((item1, item2) => new Date(item1.creation) - new Date(item2.creation)); + this.timeline_items.sort((item1, item2) => new Date(item2.creation) - new Date(item1.creation)); this.timeline_items.forEach(this.add_timeline_item.bind(this)); } } From d039655bde5fd50cb251bd282e0afec9a575fa02 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 9 Dec 2020 11:07:49 +0530 Subject: [PATCH 092/187] fix: Timeline top & bottom style --- frappe/desk/page/user_profile/user_profile.css | 4 ++++ frappe/public/scss/desk/timeline.scss | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/frappe/desk/page/user_profile/user_profile.css b/frappe/desk/page/user_profile/user_profile.css index 5d6c775474..9bcfc3394a 100644 --- a/frappe/desk/page/user_profile/user_profile.css +++ b/frappe/desk/page/user_profile/user_profile.css @@ -2,6 +2,10 @@ padding-top: 0; } +.recent-activity .new-timeline:before { + top: 25px; +} + .recent-activity-title { font-weight: 700; font-size: var(--text-xl); diff --git a/frappe/public/scss/desk/timeline.scss b/frappe/public/scss/desk/timeline.scss index 571fb0b26c..43db6fffed 100644 --- a/frappe/public/scss/desk/timeline.scss +++ b/frappe/public/scss/desk/timeline.scss @@ -28,10 +28,10 @@ $threshold: 34; &:before { content: ' '; - top: 25px; + top: 40px; // TODO: get top and bottom programmatically position: absolute; border-left: 1px solid var(--dark-border-color); - bottom: calc(-1 * var(--timeline-item-bottom-margin)); + bottom: calc(-1 * var(--timeline-item-bottom-margin) + 25px); } .timeline-dot { @include timeline-badge(16px); From b276659523ab39c2c8507d38beafa992e7f195e7 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 9 Dec 2020 11:23:09 +0530 Subject: [PATCH 093/187] fix: Share dialog input alignment --- .../js/frappe/form/templates/set_sharing.html | 97 ++++++++++--------- 1 file changed, 51 insertions(+), 46 deletions(-) diff --git a/frappe/public/js/frappe/form/templates/set_sharing.html b/frappe/public/js/frappe/form/templates/set_sharing.html index 38266b1c10..04b7946e76 100644 --- a/frappe/public/js/frappe/form/templates/set_sharing.html +++ b/frappe/public/js/frappe/form/templates/set_sharing.html @@ -1,54 +1,59 @@
-
-
{%= __("User") %}
-
{%= __("Can Read") %}
-
{%= __("Can Write") %}
-
{%= __("Can Share") %}
-
- -
- -
-
-
+
+
{%= __("User") %}
+
{%= __("Can Read") %}
+
{%= __("Can Write") %}
+
{%= __("Can Share") %}
- {% for (var i=0, l=shared.length; i < l; i++) { - var s = shared[i]; %} - {% if(s && !s.everyone) { %} -
-
{%= s.user %}
-
-
-
-
- {% } %} - {% } %} +
+ +
+
+
+
+
- {% if(frappe.model.can_share(null, frm)) { %} -
+ {% for (var i=0, l=shared.length; i < l; i++) { + var s = shared[i]; %} + {% if(s && !s.everyone) { %} +
+
{%= s.user %}
+
+
+
+
+ {% } %} + {% } %} -
-
{%= __("Share this document with") %}
-
{%= __("Can Read") %}
-
{%= __("Can Write") %}
-
{%= __("Can Share") %}
-
+ {% if(frappe.model.can_share(null, frm)) { %} +
-
-
-
-
-
-
-
- -
+
+
{%= __("Share this document with") %}
+
{%= __("Can Read") %}
+
{%= __("Can Write") %}
+
{%= __("Can Share") %}
+
+ +
+
+
+
+
+
+
+
+ +
{% endif %}
\ No newline at end of file From 240b4eb8eabfb32cab67cd3c196078876b383633 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 9 Dec 2020 11:46:16 +0530 Subject: [PATCH 094/187] refactor: Move flex styles to .scss file --- frappe/public/less/flex.less | 82 --------------------------- frappe/public/scss/common/flex.scss | 86 +++++++++++++++++++++++++++++ frappe/public/scss/desk/index.scss | 1 + 3 files changed, 87 insertions(+), 82 deletions(-) delete mode 100644 frappe/public/less/flex.less create mode 100644 frappe/public/scss/common/flex.scss diff --git a/frappe/public/less/flex.less b/frappe/public/less/flex.less deleted file mode 100644 index 12797241ce..0000000000 --- a/frappe/public/less/flex.less +++ /dev/null @@ -1,82 +0,0 @@ -.flex { - display: flex; -} - -.flex-column { - .flex; - flex-direction: column; -} - -.justify-center { - justify-content: center; -} - -.align-center { - align-items: center; -} - -.align-flex-end { - align-items: flex-end; -} - -.justify-between { - justify-content: space-between -} - -.justify-flex-end { - justify-content: flex-end; -} - -.justify-flex-start { - justify-content: flex-start; -} - -.flex-wrap { - flex-wrap: wrap; -} - -.flush-top { - display: flex; - justify-content: space-between; - align-items: flex-end; -} - -.level { - display: flex; - justify-content: space-between; - align-items: center; -} - -.level-left, .level-right { - display: flex; - flex-basis: auto; - flex-grow: 0; - flex-shrink: 0; - align-items: center; - - &.is-flexible { - flex-grow: initial; - flex-shrink: initial; - } -} - -.level-left { - justify-content: flex-start; -} - -.level-right { - justify-content: flex-end; -} - -.level-item { - align-items: center; - display: flex; - flex-basis: auto; - flex-grow: 0; - flex-shrink: 0; - justify-content: center; -} - -.fill-width { - flex: 1 -} diff --git a/frappe/public/scss/common/flex.scss b/frappe/public/scss/common/flex.scss new file mode 100644 index 0000000000..11b0635fc0 --- /dev/null +++ b/frappe/public/scss/common/flex.scss @@ -0,0 +1,86 @@ +.flex { + display: flex; +} + +.flex-column { + @extend .flex; + flex-direction: column; +} + +.justify-center { + justify-content: center; +} + +.align-center { + align-items: center; +} + +.align-flex-start { + align-items: flex-start; +} + +.align-flex-end { + align-items: flex-end; +} + +.justify-between { + justify-content: space-between +} + +.justify-flex-end { + justify-content: flex-end; +} + +.justify-flex-start { + justify-content: flex-start; +} + +.flex-wrap { + flex-wrap: wrap; +} + +.flush-top { + display: flex; + justify-content: space-between; + align-items: flex-end; +} + +.level { + display: flex; + justify-content: space-between; + align-items: center; +} + +.level-left, .level-right { + display: flex; + flex-basis: auto; + flex-grow: 0; + flex-shrink: 0; + align-items: center; + + &.is-flexible { + flex-grow: initial; + flex-shrink: initial; + } +} + +.level-left { + justify-content: flex-start; +} + +.level-right { + justify-content: flex-end; +} + +.level-item { + align-items: center; + display: flex; + flex-basis: auto; + flex-grow: 0; + flex-shrink: 0; + justify-content: center; +} + +.fill-width { + flex: 1 +} diff --git a/frappe/public/scss/desk/index.scss b/frappe/public/scss/desk/index.scss index 66c04c9f4b..0c0555ffca 100644 --- a/frappe/public/scss/desk/index.scss +++ b/frappe/public/scss/desk/index.scss @@ -41,3 +41,4 @@ @import "theme_switcher"; @import "quill"; @import "plyr"; +@import "../common/flex" From 82f0ccd0b1b36c946446ad744ee240a6867c8eef Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 9 Dec 2020 11:47:54 +0530 Subject: [PATCH 095/187] fix: Remove flex.less import from chat.less --- frappe/public/less/chat.less | 3 --- 1 file changed, 3 deletions(-) diff --git a/frappe/public/less/chat.less b/frappe/public/less/chat.less index 8b9f17c2aa..a63d24f8de 100644 --- a/frappe/public/less/chat.less +++ b/frappe/public/less/chat.less @@ -1,9 +1,6 @@ // Author - Achilles Rasquinha // http://codeguide.co - @mdo (Author of Bootstrap) - -@import "flex.less"; - // Typography @font-weight-bold: 700; @font-weight-heavy: 900; From 9a536c3c18642e0d5b8d6e06a9536cce07cdfc62 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 9 Dec 2020 12:07:10 +0530 Subject: [PATCH 096/187] fix: Re-arrange flex import --- frappe/public/scss/desk/index.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/public/scss/desk/index.scss b/frappe/public/scss/desk/index.scss index 0c0555ffca..eb82178dea 100644 --- a/frappe/public/scss/desk/index.scss +++ b/frappe/public/scss/desk/index.scss @@ -4,6 +4,7 @@ @import "~bootstrap/scss/bootstrap"; @import "global"; +@import "../common/flex"; @import "form"; @import "print_preview"; @import "list"; @@ -40,5 +41,4 @@ @import "user_profile"; @import "theme_switcher"; @import "quill"; -@import "plyr"; -@import "../common/flex" +@import "plyr"; \ No newline at end of file From 06cb64f8305b557b29022d6c61e4ef47401488fe Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 9 Dec 2020 12:28:46 +0530 Subject: [PATCH 097/187] fix: Temp style file for summary separator --- frappe/public/scss/desk/report.scss | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/frappe/public/scss/desk/report.scss b/frappe/public/scss/desk/report.scss index 4f87fcd0a8..ba7457aae3 100644 --- a/frappe/public/scss/desk/report.scss +++ b/frappe/public/scss/desk/report.scss @@ -209,17 +209,18 @@ .summary-value { // FORM background: var(--card-bg); - border-radius: var(--border-radius, 6px); - box-shadow: var(--shadow-sm); + border-radius: var(--border-radius-sm, 4px); + border: 1px solid var(--dark-border-color); &.green { color: var(--green-500); } &.red { color: var(--red-500); } &.blue { color: var(--blue-500); } // SIZE & SPACING - min-width: 30px; + min-width: 24px; + min-height: 24px; margin: 0px 30px; - padding: 2px 8px; + line-height: 1; // LAYOUT display: flex; From c70a83c91d05ad0b4f72e7ee984723be0f2db53f Mon Sep 17 00:00:00 2001 From: prssanna Date: Wed, 9 Dec 2020 13:08:08 +0530 Subject: [PATCH 098/187] fix: don't separate files and folders --- .../public/js/frappe/views/file/file_view.js | 82 ++++++------------- 1 file changed, 27 insertions(+), 55 deletions(-) diff --git a/frappe/public/js/frappe/views/file/file_view.js b/frappe/public/js/frappe/views/file/file_view.js index 5c88d9a536..a19286c962 100644 --- a/frappe/public/js/frappe/views/file/file_view.js +++ b/frappe/public/js/frappe/views/file/file_view.js @@ -243,66 +243,38 @@ frappe.views.FileView = class FileView extends frappe.views.ListView { } } - get_item_html(d, draggable) { - const icon_class = d.icon_class + '-large'; - let file_body_html = - d._type == 'image' + render_grid_view() { + let html = this.data.map(d => { + const icon_class = d.icon_class + '-large'; + let file_body_html = d._type == 'image' ? `
${
 						d.file_name
-				  }
` + }">
` : frappe.utils.icon(icon_class, { width: '40px', height: '45px' }); - const name = escape(d.name); - return ` -
-
- -
-
- ${file_body_html} -
- -
- `; - } - - render_grid_view() { - let folders_html = ''; - let files_html = ''; - - this.data.map((d) => { - d = this.prepare_datum(d); - if (d._type == 'folder') folders_html += this.get_item_html(d, false); - else files_html += this.get_item_html(d, true); - }); - - let get_html = (type, body_html) => { - if (body_html) { - const title = frappe.model.unscrub(type); - return `
- - ${__(title)} -
-
- ${body_html} -
`; - } - return ''; - }; - - let html = `
- ${get_html('folders', folders_html)} - ${get_html('files', files_html)} -
`; + const name = escape(d.name); + const draggable = d.type == 'Folder' ? false : true; + return ` + +
+ +
+
+ ${file_body_html} +
+ +
+ `; + }).join(''); this.$result.addClass('file-grid-view'); - this.$result.empty().html(html); + this.$result.empty().html( + `
+ ${html} +
` + ); } get_breadcrumbs_html() { From 00492a4e7541d0665b89f3575fc05ede10166c76 Mon Sep 17 00:00:00 2001 From: prssanna Date: Wed, 9 Dec 2020 13:08:56 +0530 Subject: [PATCH 099/187] fix: file checkbox click issue --- frappe/public/js/frappe/list/list_view.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 76c0e82549..0c4322382d 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -1083,7 +1083,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { } setup_list_click() { - this.$result.on("click", ".list-row, .image-view-header", (e) => { + this.$result.on("click", ".list-row, .image-view-header, .file-header", (e) => { const $target = $(e.target); // tick checkbox if Ctrl/Meta key is pressed if (e.ctrlKey || (e.metaKey && !$target.is("a"))) { @@ -1101,6 +1101,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { $target.is(":checkbox") || $target.is("a") ) { + e.stopPropagation(); return; } // open form From 947c410953a236c709599e6ef81ea7041421caf2 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 9 Dec 2020 13:22:50 +0530 Subject: [PATCH 100/187] fix: Extra space issue in assign and share button --- .../js/frappe/form/sidebar/assign_to.js | 35 +++++-------------- frappe/public/js/frappe/form/sidebar/share.js | 14 ++++++-- 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/frappe/public/js/frappe/form/sidebar/assign_to.js b/frappe/public/js/frappe/form/sidebar/assign_to.js index f8461d1fdf..635e54d9b3 100644 --- a/frappe/public/js/frappe/form/sidebar/assign_to.js +++ b/frappe/public/js/frappe/form/sidebar/assign_to.js @@ -21,25 +21,21 @@ frappe.ui.form.AssignTo = Class.extend({ }, render: function(assignments) { this.frm.get_docinfo().assignments = assignments; - this.parent.find(".assignment-row").remove(); - - if (this.primary_action) { - this.primary_action.remove(); - this.primary_action = null; - } - - if (this.dialog) { - this.dialog.hide(); - } let assignments_wrapper = this.parent.find('.assignments'); assignments_wrapper.empty(); let assigned_users = assignments.map(d => d.owner); + + if (!assigned_users.length) { + assignments_wrapper.hide(); + return; + } + let avatar_group = frappe.avatar_group(assigned_users, 5, {'align': 'left', 'overlap': true}); + assignments_wrapper.show(); assignments_wrapper.append(avatar_group); - avatar_group.click(() => { new frappe.ui.form.AssignmentDialog({ assignments: assigned_users, @@ -48,28 +44,15 @@ frappe.ui.form.AssignTo = Class.extend({ }); }); }, - get_assignment_block(info) { - let remove_action = false; - if (info.owner === frappe.session.user || this.frm.perm[0].write) { - remove_action = this.remove.bind(this); - } - return $(`
  • `) - .append(frappe.get_data_pill( - frappe.user.full_name(info.owner), - info.owner, - remove_action, - frappe.avatar(info.owner, "avatar-xs") - )); - }, add: function() { var me = this; - if(this.frm.is_new()) { + if (this.frm.is_new()) { frappe.throw(__("Please save the document before assignment")); return; } - if(!me.assign_to) { + if (!me.assign_to) { me.assign_to = new frappe.ui.form.AssignToDialog({ method: "frappe.desk.form.assign_to.add", doctype: me.frm.doctype, diff --git a/frappe/public/js/frappe/form/sidebar/share.js b/frappe/public/js/frappe/form/sidebar/share.js index b1b023ebba..2a3b652372 100644 --- a/frappe/public/js/frappe/form/sidebar/share.js +++ b/frappe/public/js/frappe/form/sidebar/share.js @@ -12,12 +12,9 @@ frappe.ui.form.Share = Class.extend({ this.render_sidebar(); }, render_sidebar: function() { - this.shares.empty(); const shared = this.shared || this.frm.get_docinfo().shared; const shared_users = shared.filter(Boolean).map(s => s.user); - // REDESIGN-TODO: handle "shared with everyone" - this.shares.append(frappe.avatar_group(shared_users, 5, {'align': 'left', 'overlap': true})); if (this.frm.is_new()) { this.parent.find(".share-doc-btn").hide(); } @@ -25,6 +22,17 @@ frappe.ui.form.Share = Class.extend({ this.parent.find(".share-doc-btn").on("click", () => { this.frm.share_doc(); }); + + this.shares.empty(); + + if (!shared_users.length) { + this.shares.hide(); + return; + } + + this.shares.show(); + // REDESIGN-TODO: handle "shared with everyone" + this.shares.append(frappe.avatar_group(shared_users, 5, {'align': 'left', 'overlap': true})); }, show: function() { var me = this; From 737674487abe51fc3ef27683caaa23dedd2e6f47 Mon Sep 17 00:00:00 2001 From: prssanna Date: Wed, 9 Dec 2020 14:12:54 +0530 Subject: [PATCH 101/187] fix: hide list activity in mobile screens --- frappe/public/js/frappe/list/list_view.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 0c4322382d..e71f79cdac 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -831,8 +831,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { `; html += ` -
    - +