From 9e139171f41405d677d62361fb2ef2190d475d5e Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 8 Apr 2020 18:35:49 +0530
Subject: [PATCH 001/307] feat: custom form dashboards
---
frappe/custom/doctype/custom_link/__init__.py | 0
.../custom/doctype/custom_link/custom_link.js | 16 ++++++
.../doctype/custom_link/custom_link.json | 52 +++++++++++++++++++
.../custom/doctype/custom_link/custom_link.py | 43 +++++++++++++++
.../doctype/custom_link/test_custom_link.py | 10 ++++
frappe/desk/form/meta.py | 2 -
frappe/desk/notifications.py | 7 +--
frappe/model/meta.py | 4 +-
8 files changed, 128 insertions(+), 6 deletions(-)
create mode 100644 frappe/custom/doctype/custom_link/__init__.py
create mode 100644 frappe/custom/doctype/custom_link/custom_link.js
create mode 100644 frappe/custom/doctype/custom_link/custom_link.json
create mode 100644 frappe/custom/doctype/custom_link/custom_link.py
create mode 100644 frappe/custom/doctype/custom_link/test_custom_link.py
diff --git a/frappe/custom/doctype/custom_link/__init__.py b/frappe/custom/doctype/custom_link/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frappe/custom/doctype/custom_link/custom_link.js b/frappe/custom/doctype/custom_link/custom_link.js
new file mode 100644
index 0000000000..f1c06daeeb
--- /dev/null
+++ b/frappe/custom/doctype/custom_link/custom_link.js
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, Frappe Technologies and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Custom Link', {
+ refresh: function(frm) {
+ frm.set_query("document_type", function () {
+ return {
+ filters: {
+ custom: 0,
+ istable: 0,
+ module: ['not in', ["Email", "Core", "Custom", "Event Streaming", "Social", "Data Migration", "Geo", "Desk"]]
+ }
+ }
+ });
+ }
+});
diff --git a/frappe/custom/doctype/custom_link/custom_link.json b/frappe/custom/doctype/custom_link/custom_link.json
new file mode 100644
index 0000000000..350e6b1c2d
--- /dev/null
+++ b/frappe/custom/doctype/custom_link/custom_link.json
@@ -0,0 +1,52 @@
+{
+ "actions": [],
+ "autoname": "field:document_type",
+ "creation": "2020-04-08 15:16:44.342509",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "document_type",
+ "links"
+ ],
+ "fields": [
+ {
+ "fieldname": "document_type",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Document Type",
+ "options": "DocType",
+ "reqd": 1,
+ "unique": 1
+ },
+ {
+ "fieldname": "links",
+ "fieldtype": "Table",
+ "label": "Links",
+ "options": "DocType Link"
+ }
+ ],
+ "links": [],
+ "modified": "2020-04-08 16:42:59.402671",
+ "modified_by": "Administrator",
+ "module": "Custom",
+ "name": "Custom Link",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/frappe/custom/doctype/custom_link/custom_link.py b/frappe/custom/doctype/custom_link/custom_link.py
new file mode 100644
index 0000000000..b9a88b58f2
--- /dev/null
+++ b/frappe/custom/doctype/custom_link/custom_link.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class CustomLink(Document):
+ pass
+
+def get_custom_doctype_links(doctype, data):
+ if frappe.get_all("Custom Link", {"document_type": doctype}):
+ doc = frappe.get_doc("Custom Link", doctype)
+
+ if not data.transactions:
+ # init groups
+ data.transactions = []
+ data.non_standard_fieldnames = {}
+
+ for link in doc.links:
+ link.added = False
+ for group in data.transactions:
+ # group found
+ if group.get("label") == link.group:
+ if not link.link_doctype in group.get("items"):
+ group.get("items").append(link.link_doctype)
+ link.added = True
+
+ if not link.added:
+ # group not found, make a new group
+ data.transactions.append({
+ "label": link.group,
+ "items": [link.link_doctype]
+ })
+
+ if link.link_fieldname != data.fieldname:
+ if data.fieldname:
+ data.non_standard_fieldnames[link.link_doctype] = link.link_fieldname
+ else:
+ data.fieldname = link.link_fieldname
+
+ return data
\ No newline at end of file
diff --git a/frappe/custom/doctype/custom_link/test_custom_link.py b/frappe/custom/doctype/custom_link/test_custom_link.py
new file mode 100644
index 0000000000..a292f73ad0
--- /dev/null
+++ b/frappe/custom/doctype/custom_link/test_custom_link.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestCustomLink(unittest.TestCase):
+ pass
diff --git a/frappe/desk/form/meta.py b/frappe/desk/form/meta.py
index 26fc6037fd..ba0e5c2216 100644
--- a/frappe/desk/form/meta.py
+++ b/frappe/desk/form/meta.py
@@ -196,8 +196,6 @@ class FormMeta(Meta):
self.get("__messages").update(messages, as_value=True)
def load_dashboard(self):
- if self.custom:
- return
self.set('__dashboard', self.get_dashboard_data())
def load_kanban_meta(self):
diff --git a/frappe/desk/notifications.py b/frappe/desk/notifications.py
index 3a8815ca71..109dd25f4f 100644
--- a/frappe/desk/notifications.py
+++ b/frappe/desk/notifications.py
@@ -268,8 +268,9 @@ def get_open_count(doctype, name, items=[]):
"count": out,
}
- module = frappe.get_meta_module(doctype)
- if hasattr(module, "get_timeline_data"):
- out["timeline_data"] = module.get_timeline_data(doctype, name)
+ if not meta.custom:
+ module = frappe.get_meta_module(doctype)
+ if hasattr(module, "get_timeline_data"):
+ out["timeline_data"] = module.get_timeline_data(doctype, name)
return out
diff --git a/frappe/model/meta.py b/frappe/model/meta.py
index 5065684311..e6a89be108 100644
--- a/frappe/model/meta.py
+++ b/frappe/model/meta.py
@@ -26,6 +26,7 @@ from frappe.model.base_document import BaseDocument
from frappe.modules import load_doctype_module
from frappe.model.workflow import get_workflow_name
from frappe import _
+from frappe.custom.doctype.custom_link.custom_link import get_custom_doctype_links
def get_meta(doctype, cached=True):
if cached:
@@ -429,6 +430,7 @@ class Meta(Document):
pass
self.add_doctype_links(data)
+ get_custom_doctype_links(self.name, data)
for hook in frappe.get_hooks("override_doctype_dashboards", {}).get(self.name, []):
data = frappe.get_attr(hook)(data=data)
@@ -447,7 +449,7 @@ class Meta(Document):
link.added = False
for group in data.transactions:
# group found
- if group.label == link.label:
+ if group.label == link.group:
if not link.link_doctype in group.items:
group.items.append(link.link_doctype)
link.added = True
From a25088a606dd50a293d1f6b542af9b8c75e8cd5e Mon Sep 17 00:00:00 2001
From: "Chinmay D. Pai"
Date: Mon, 13 Apr 2020 19:10:19 +0530
Subject: [PATCH 002/307] chore: show message on migrate when services are not
running
shows message before migrate if the database or redis service is not running
instead of trying to migrate and then failing.
Signed-off-by: Chinmay D. Pai
---
frappe/migrate.py | 16 +++++++++++++
frappe/utils/connections.py | 48 +++++++++++++++++++++++++++++++++++++
2 files changed, 64 insertions(+)
create mode 100644 frappe/utils/connections.py
diff --git a/frappe/migrate.py b/frappe/migrate.py
index 043b6817d7..711f51c57a 100644
--- a/frappe/migrate.py
+++ b/frappe/migrate.py
@@ -5,11 +5,13 @@ from __future__ import unicode_literals
import json
import os
+import sys
import frappe
import frappe.translate
import frappe.modules.patch_handler
import frappe.model.sync
from frappe.utils.fixtures import sync_fixtures
+from frappe.utils.connections import check_connection
from frappe.cache_manager import clear_global_cache
from frappe.desk.notifications import clear_notifications
from frappe.website import render
@@ -18,6 +20,7 @@ from frappe.modules.utils import sync_customizations
from frappe.core.doctype.scheduled_job_type.scheduled_job_type import sync_jobs
from frappe.utils import global_search
+
def migrate(verbose=True, rebuild_website=False, skip_failing=False):
'''Migrate all apps to the latest version, will:
- run before migrate hooks
@@ -30,6 +33,19 @@ def migrate(verbose=True, rebuild_website=False, skip_failing=False):
- run after migrate hooks
'''
+ service_status = check_connection(redis_services=["redis_cache"])
+ if False in service_status.values():
+ for service in service_status:
+ if not service_status.get(service, True):
+ print("{} service is not running.".format(service))
+ print("""Cannot run bench migrate without the services running.
+If you are running bench in development mode, make sure that bench is running:
+
+$ bench start
+
+Otherwise, check the server logs and ensure that all the required services are running.""")
+ sys.exit(1)
+
touched_tables_file = frappe.get_site_path('touched_tables.json')
if os.path.exists(touched_tables_file):
os.remove(touched_tables_file)
diff --git a/frappe/utils/connections.py b/frappe/utils/connections.py
new file mode 100644
index 0000000000..57b9399986
--- /dev/null
+++ b/frappe/utils/connections.py
@@ -0,0 +1,48 @@
+import socket
+
+from six.moves.urllib.parse import urlparse
+from frappe import get_conf
+
+config = get_conf()
+REDIS_KEYS = ('redis_cache', 'redis_queue', 'redis_socketio')
+
+
+def is_open(ip, port, timeout=10):
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.settimeout(timeout)
+ try:
+ s.connect((ip, int(port)))
+ s.shutdown(socket.SHUT_RDWR)
+ return True
+ except socket.error:
+ return False
+ finally:
+ s.close()
+
+
+def check_database():
+ db_type = config.get("db_type", "mariadb")
+ if db_type == "mariadb":
+ db_host = config.get("db_host", "localhost")
+ db_port = config.get("db_port", 3306)
+ else:
+ db_host = "localhost"
+ db_port = 5342
+ return {"db_type": is_open(db_host, db_port)}
+
+
+def check_redis(redis_services=None):
+ services = redis_services or REDIS_KEYS
+ status = {}
+ for conn in services:
+ redis_url = urlparse(config.get(conn)).netloc
+ redis_host, redis_port = redis_url.split(":")
+ status[conn] = is_open(redis_host, redis_port)
+ return status
+
+
+def check_connection(redis_services=None):
+ service_status = {}
+ service_status.update(check_database())
+ service_status.update(check_redis(redis_services))
+ return service_status
From 318e397ab35cb0508ea8697b0088f23c37e67df2 Mon Sep 17 00:00:00 2001
From: "Chinmay D. Pai"
Date: Mon, 13 Apr 2020 19:13:43 +0530
Subject: [PATCH 003/307] chore: unquote db_type
Signed-off-by: Chinmay D. Pai
---
frappe/utils/connections.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/frappe/utils/connections.py b/frappe/utils/connections.py
index 57b9399986..bffbd98134 100644
--- a/frappe/utils/connections.py
+++ b/frappe/utils/connections.py
@@ -28,7 +28,7 @@ def check_database():
else:
db_host = "localhost"
db_port = 5342
- return {"db_type": is_open(db_host, db_port)}
+ return {db_type: is_open(db_host, db_port)}
def check_redis(redis_services=None):
From c0d0fcfd69227562069933449881d27470bb904b Mon Sep 17 00:00:00 2001
From: "Chinmay D. Pai"
Date: Mon, 13 Apr 2020 19:24:51 +0530
Subject: [PATCH 004/307] chore: do not hardcode anything for postgres
Signed-off-by: Chinmay D. Pai
---
frappe/utils/connections.py | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/frappe/utils/connections.py b/frappe/utils/connections.py
index bffbd98134..6bd24d57ec 100644
--- a/frappe/utils/connections.py
+++ b/frappe/utils/connections.py
@@ -22,12 +22,8 @@ def is_open(ip, port, timeout=10):
def check_database():
db_type = config.get("db_type", "mariadb")
- if db_type == "mariadb":
- db_host = config.get("db_host", "localhost")
- db_port = config.get("db_port", 3306)
- else:
- db_host = "localhost"
- db_port = 5342
+ db_host = config.get("db_host", "localhost")
+ db_port = config.get("db_port", 3306 if db_type == "mariadb" else 5342)
return {db_type: is_open(db_host, db_port)}
From fca6181d6771235d883bd1c4cc0ce57c3c32065c Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 15 Apr 2020 21:32:22 +0530
Subject: [PATCH 005/307] feat: multiple assignments
---
frappe/desk/form/assign_to.py | 77 +++----
.../js/frappe/form/sidebar/assign_to.js | 202 +++++++++++-------
2 files changed, 164 insertions(+), 115 deletions(-)
diff --git a/frappe/desk/form/assign_to.py b/frappe/desk/form/assign_to.py
index 76c7caa63d..a0f2f99910 100644
--- a/frappe/desk/form/assign_to.py
+++ b/frappe/desk/form/assign_to.py
@@ -11,6 +11,7 @@ from frappe.desk.doctype.notification_log.notification_log import enqueue_create
get_title, get_title_html
import frappe.utils
import frappe.share
+import json
class DuplicateToDoError(frappe.ValidationError): pass
@@ -19,7 +20,7 @@ def get(args=None):
if not args:
args = frappe.local.form_dict
- return frappe.get_all('ToDo', fields = ['owner', 'description'], filters = dict(
+ return frappe.get_all('ToDo', fields = ['owner', 'name'], filters = dict(
reference_type = args.get('doctype'),
reference_name = args.get('name'),
status = ('!=', 'Cancelled')
@@ -40,49 +41,53 @@ def add(args=None):
if not args:
args = frappe.local.form_dict
- if frappe.db.sql("""SELECT `owner`
- FROM `tabToDo`
- WHERE `reference_type`=%(doctype)s
- AND `reference_name`=%(name)s
- AND `status`='Open'
- AND `owner`=%(assign_to)s""", args):
- frappe.throw(_("Already in user's To Do list"), DuplicateToDoError)
- else:
- from frappe.utils import nowdate
-
- if not args.get('description'):
- args['description'] = _('Assignment for {0} {1}').format(args['doctype'], args['name'])
-
- d = frappe.get_doc({
- "doctype":"ToDo",
- "owner": args['assign_to'],
+ for assign_to in json.loads(args.get("assign_to")):
+ filters = {
"reference_type": args['doctype'],
"reference_name": args['name'],
- "description": args.get('description'),
- "priority": args.get("priority", "Medium"),
"status": "Open",
- "date": args.get('date', nowdate()),
- "assigned_by": args.get('assigned_by', frappe.session.user),
- 'assignment_rule': args.get('assignment_rule')
- }).insert(ignore_permissions=True)
+ "owner": assign_to
+ }
- # set assigned_to if field exists
- if frappe.get_meta(args['doctype']).get_field("assigned_to"):
- frappe.db.set_value(args['doctype'], args['name'], "assigned_to", args['assign_to'])
+ if frappe.get_all("ToDo", filters=filters):
+ if not args.get("bulk_assign"):
+ frappe.throw(_("Already in user's ToDo list"), DuplicateToDoError)
+ else:
+ from frappe.utils import nowdate
- doc = frappe.get_doc(args['doctype'], args['name'])
+ if not args.get('description'):
+ args['description'] = _('Assignment for {0} {1}').format(args['doctype'], args['name'])
- # if assignee does not have permissions, share
- if not frappe.has_permission(doc=doc, user=args['assign_to']):
- frappe.share.add(doc.doctype, doc.name, args['assign_to'])
- frappe.msgprint(_('Shared with user {0} with read access').format(args['assign_to']), alert=True)
+ d = frappe.get_doc({
+ "doctype":"ToDo",
+ "owner": assign_to,
+ "reference_type": args['doctype'],
+ "reference_name": args['name'],
+ "description": args.get('description'),
+ "priority": args.get("priority", "Medium"),
+ "status": "Open",
+ "date": args.get('date', nowdate()),
+ "assigned_by": args.get('assigned_by', frappe.session.user),
+ 'assignment_rule': args.get('assignment_rule')
+ }).insert(ignore_permissions=True)
- # make this document followed by assigned user
- follow_document(args['doctype'], args['name'], args['assign_to'])
+ # set assigned_to if field exists
+ if frappe.get_meta(args['doctype']).get_field("assigned_to"):
+ frappe.db.set_value(args['doctype'], args['name'], "assigned_to", assign_to)
- # notify
- notify_assignment(d.assigned_by, d.owner, d.reference_type, d.reference_name, action='ASSIGN',\
- description=args.get("description"))
+ doc = frappe.get_doc(args['doctype'], args['name'])
+
+ # if assignee does not have permissions, share
+ if not frappe.has_permission(doc=doc, user=assign_to):
+ frappe.share.add(doc.doctype, doc.name, assign_to)
+ frappe.msgprint(_('Shared with user {0} with read access').format(assign_to, alert=True))
+
+ # make this document followed by assigned user
+ follow_document(args['doctype'], args['name'], assign_to)
+
+ # notify
+ notify_assignment(d.assigned_by, d.owner, d.reference_type, d.reference_name, action='ASSIGN',\
+ description=args.get("description"))
return get(args)
diff --git a/frappe/public/js/frappe/form/sidebar/assign_to.js b/frappe/public/js/frappe/form/sidebar/assign_to.js
index 61d1789518..b78540f6a7 100644
--- a/frappe/public/js/frappe/form/sidebar/assign_to.js
+++ b/frappe/public/js/frappe/form/sidebar/assign_to.js
@@ -87,23 +87,17 @@ frappe.ui.form.AssignTo = Class.extend({
if(!me.assign_to) {
me.assign_to = new frappe.ui.form.AssignToDialog({
- obj: me,
- method: 'frappe.desk.form.assign_to.add',
+ method: "frappe.desk.form.assign_to.add",
doctype: me.frm.doctype,
docname: me.frm.docname,
- callback: function(r) {
+ frm: me.frm,
+ callback: function (r) {
me.render(r.message);
}
});
}
me.assign_to.dialog.clear();
-
- if(me.frm.meta.title_field) {
- me.assign_to.dialog.set_value("description", me.frm.doc[me.frm.meta.title_field])
- }
-
me.assign_to.dialog.show();
- me.assign_to = null;
},
remove: function(owner) {
var me = this;
@@ -130,81 +124,131 @@ frappe.ui.form.AssignTo = Class.extend({
frappe.ui.form.AssignToDialog = Class.extend({
init: function(opts){
- var me = this
- var dialog = new frappe.ui.Dialog({
- title: __('Add to To Do'),
- fields: [
- { fieldtype: 'Link', fieldname: 'assign_to', options: 'User', label: __("Assign To"), reqd: true, filters: { 'user_type': 'System User' }},
- { fieldtype: 'Check', fieldname: 'myself', label: __("Assign to me"), "default": 0 },
- { fieldtype: 'Small Text', fieldname: 'description', label: __("Comment") },
- { fieldtype: 'Section Break' },
- { fieldtype: 'Column Break' },
- { fieldtype: 'Date', fieldname: 'date', label: __("Complete By") },
- { fieldtype: 'Column Break' },
- { fieldtype: 'Select', fieldname: 'priority', label: __("Priority"),
- options: [
- { value: 'Low', label: __('Low') },
- { value: 'Medium', label: __('Medium') },
- { value: 'High', label: __('High') }
- ],
- // Pick up priority from the source document, if it exists and is available in ToDo
- 'default': ["Low", "Medium", "High"].includes(opts.obj.frm && opts.obj.frm.doc.priority
- ? opts.obj.frm.doc.priority : 'Medium')
- },
- ],
- primary_action: function() { frappe.ui.add_assignment(opts, this) },
- primary_action_label: __("Add")
- })
- $.extend(me, dialog);
+ $.extend(this, opts)
- me.dialog = dialog;
-
- me.dialog.fields_dict.assign_to.get_query = "frappe.core.doctype.user.user.user_query";
-
- var myself = me.dialog.get_input("myself").on("click", function() {
- me.toggle_myself(this);
- });
- me.toggle_myself(myself);
- },
- toggle_myself: function(myself) {
- var me = this;
- if($(myself).prop("checked")) {
- me.dialog.set_value("assign_to", frappe.session.user);
- me.dialog.get_field("notify").$wrapper.toggle(false);
- me.dialog.get_field("assign_to").$wrapper.toggle(false);
- } else {
- me.dialog.set_value("assign_to", "");
- me.dialog.get_field("assign_to").$wrapper.toggle(true);
- }
+ this.make();
+ this.set_description_from_doc();
},
+ make: function() {
+ let me = this
-});
+ me.dialog = new frappe.ui.Dialog({
+ title: __('Add to ToDo'),
+ fields: me.get_fields(),
+ primary_action_label: __("Add"),
+ primary_action: function() {
+ let args = me.dialog.get_values();
-frappe.ui.add_assignment = function(opts, dialog) {
- var assign_to = dialog.fields_dict.assign_to.get_value();
- var args = dialog.get_values();
- if(args && assign_to) {
- dialog.set_message('Assigning...');
- return frappe.call({
- method: opts.method,
- args: $.extend(args, {
- doctype: opts.doctype,
- name: opts.docname,
- assign_to: assign_to,
- bulk_assign: opts.bulk_assign || false,
- re_assign: opts.re_assign || false
- }),
- btn: dialog.get_primary_btn(),
- callback: function(r) {
- if(!r.exc) {
- if(opts.callback){
- opts.callback(r);
- }
- dialog && dialog.hide();
- } else {
- dialog.clear_message();
+ if (args && args.assign_to) {
+ me.dialog.set_message("Assigning...");
+
+ frappe.call({
+ method: me.method,
+ args: $.extend(args, {
+ doctype: me.doctype,
+ name: me.docname,
+ assign_to: args.assign_to,
+ bulk_assign: me.bulk_assign || false,
+ re_assign: me.re_assign || false
+ }),
+ btn: me.dialog.get_primary_btn(),
+ callback: function(r) {
+ if (!r.exc) {
+ if (me.callback) {
+ me.callback(r);
+ }
+ me.dialog && me.dialog.hide();
+ } else {
+ me.dialog.clear_message();
+ }
+ },
+ });
}
},
});
+ },
+ assign_to_me: function() {
+ let me = this;
+ let assign_to = [];
+
+ if(me.dialog.get_value("assign_to_me")) {
+ assign_to.push(frappe.session.user);
+ }
+
+ me.dialog.set_value("assign_to", assign_to);
+ },
+ set_description_from_doc: function() {
+ let me = this;
+
+ if (me.frm && me.frm.meta.title_field) {
+ me.dialog.set_value("description", me.frm.doc[me.frm.meta.title_field]);
+ }
+ },
+ set_assign_to_field_description: function() {
+ let me = this;
+
+ let assignees = me.dialog.get_value("assign_to");
+ let field = me.dialog.get_field("assign_to");
+ let description = "";
+
+ if (assignees.length > 0) {
+ description = "Assign To: " + assignees.join(", ");
+ }
+
+ field.set_description(description);
+ },
+ get_fields: function() {
+ let me = this;
+
+ return [
+ {
+ fieldtype: 'MultiSelectList',
+ fieldname: 'assign_to',
+ label: __("Assign To"),
+ reqd: true,
+ get_data: function(txt) {
+ return frappe.db.get_link_options("User", txt, {user_type: "System User", enabled: 1});
+ },
+ onchange: () => me.set_assign_to_field_description()
+ },
+ {
+ label: __("Assign to me"),
+ fieldtype: 'Check',
+ fieldname: 'assign_to_me',
+ default: 0,
+ onchange: () => me.assign_to_me()
+ },
+ {
+ label: __("Comment"),
+ fieldtype: 'Small Text',
+ fieldname: 'description'
+ },
+ {
+ fieldtype: 'Section Break'
+ },
+ {
+ fieldtype: 'Column Break'
+ },
+ {
+ label: __("Complete By"),
+ fieldtype: 'Date',
+ fieldname: 'date'
+ },
+ {
+ fieldtype: 'Column Break'
+ },
+ {
+ label: __("Priority"),
+ fieldtype: 'Select',
+ fieldname: 'priority',
+ options: [
+ { value: 'Low', label: __('Low') },
+ { value: 'Medium', label: __('Medium') },
+ { value: 'High', label: __('High') }
+ ],
+ // Pick up priority from the source document, if it exists and is available in ToDo
+ default: ["Low", "Medium", "High"].includes(me.frm && me.frm.doc.priority ? me.frm.doc.priority : 'Medium')
+ }
+ ]
}
-}
+});
From 6b9de21d539d4a64fe82473be994af9bc814eb61 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 15 Apr 2020 22:20:23 +0530
Subject: [PATCH 006/307] fix: minor bug fixes for notifying assignees
---
frappe/desk/form/assign_to.py | 4 ++--
frappe/public/js/frappe/form/sidebar/assign_to.js | 8 ++++----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/frappe/desk/form/assign_to.py b/frappe/desk/form/assign_to.py
index a0f2f99910..8a8219eb22 100644
--- a/frappe/desk/form/assign_to.py
+++ b/frappe/desk/form/assign_to.py
@@ -85,8 +85,8 @@ def add(args=None):
# make this document followed by assigned user
follow_document(args['doctype'], args['name'], assign_to)
- # notify
- notify_assignment(d.assigned_by, d.owner, d.reference_type, d.reference_name, action='ASSIGN',\
+ # notify
+ notify_assignment(d.assigned_by, d.owner, d.reference_type, d.reference_name, action='ASSIGN',\
description=args.get("description"))
return get(args)
diff --git a/frappe/public/js/frappe/form/sidebar/assign_to.js b/frappe/public/js/frappe/form/sidebar/assign_to.js
index b78540f6a7..03fba17ec7 100644
--- a/frappe/public/js/frappe/form/sidebar/assign_to.js
+++ b/frappe/public/js/frappe/form/sidebar/assign_to.js
@@ -124,7 +124,7 @@ frappe.ui.form.AssignTo = Class.extend({
frappe.ui.form.AssignToDialog = Class.extend({
init: function(opts){
- $.extend(this, opts)
+ $.extend(this, opts);
this.make();
this.set_description_from_doc();
@@ -148,7 +148,7 @@ frappe.ui.form.AssignToDialog = Class.extend({
doctype: me.doctype,
name: me.docname,
assign_to: args.assign_to,
- bulk_assign: me.bulk_assign || false,
+ bulk_assign: me.bulk_assign || false,
re_assign: me.re_assign || false
}),
btn: me.dialog.get_primary_btn(),
@@ -171,7 +171,7 @@ frappe.ui.form.AssignToDialog = Class.extend({
let me = this;
let assign_to = [];
- if(me.dialog.get_value("assign_to_me")) {
+ if (me.dialog.get_value("assign_to_me")) {
assign_to.push(frappe.session.user);
}
@@ -249,6 +249,6 @@ frappe.ui.form.AssignToDialog = Class.extend({
// Pick up priority from the source document, if it exists and is available in ToDo
default: ["Low", "Medium", "High"].includes(me.frm && me.frm.doc.priority ? me.frm.doc.priority : 'Medium')
}
- ]
+ ];
}
});
From 7886365c090ad1b645b63c0987af83e13366b1e9 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 15 Apr 2020 22:48:58 +0530
Subject: [PATCH 007/307] chore: code cleanup
---
frappe/desk/form/assign_to.py | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/frappe/desk/form/assign_to.py b/frappe/desk/form/assign_to.py
index 8a8219eb22..be83dc957e 100644
--- a/frappe/desk/form/assign_to.py
+++ b/frappe/desk/form/assign_to.py
@@ -20,11 +20,11 @@ def get(args=None):
if not args:
args = frappe.local.form_dict
- return frappe.get_all('ToDo', fields = ['owner', 'name'], filters = dict(
+ return frappe.get_all('ToDo', fields=['owner', 'name'], filters=dict(
reference_type = args.get('doctype'),
reference_name = args.get('name'),
status = ('!=', 'Cancelled')
- ), limit = 5)
+ ), limit=5)
@frappe.whitelist()
def add(args=None):
@@ -59,7 +59,7 @@ def add(args=None):
args['description'] = _('Assignment for {0} {1}').format(args['doctype'], args['name'])
d = frappe.get_doc({
- "doctype":"ToDo",
+ "doctype": "ToDo",
"owner": assign_to,
"reference_type": args['doctype'],
"reference_name": args['name'],
@@ -86,15 +86,13 @@ def add(args=None):
follow_document(args['doctype'], args['name'], assign_to)
# notify
- notify_assignment(d.assigned_by, d.owner, d.reference_type, d.reference_name, action='ASSIGN',\
+ notify_assignment(d.assigned_by, d.owner, d.reference_type, d.reference_name, action='ASSIGN',
description=args.get("description"))
return get(args)
@frappe.whitelist()
def add_multiple(args=None):
- import json
-
if not args:
args = frappe.local.form_dict
From 7dac9e2a0342809453bdb44d0588606715b5154b Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Thu, 16 Apr 2020 21:55:52 +0530
Subject: [PATCH 008/307] fix: change to multiselect pills
---
.../js/frappe/form/sidebar/assign_to.js | 33 ++++++++-----------
1 file changed, 14 insertions(+), 19 deletions(-)
diff --git a/frappe/public/js/frappe/form/sidebar/assign_to.js b/frappe/public/js/frappe/form/sidebar/assign_to.js
index 03fba17ec7..84fde564c0 100644
--- a/frappe/public/js/frappe/form/sidebar/assign_to.js
+++ b/frappe/public/js/frappe/form/sidebar/assign_to.js
@@ -184,32 +184,18 @@ frappe.ui.form.AssignToDialog = Class.extend({
me.dialog.set_value("description", me.frm.doc[me.frm.meta.title_field]);
}
},
- set_assign_to_field_description: function() {
- let me = this;
-
- let assignees = me.dialog.get_value("assign_to");
- let field = me.dialog.get_field("assign_to");
- let description = "";
-
- if (assignees.length > 0) {
- description = "Assign To: " + assignees.join(", ");
- }
-
- field.set_description(description);
- },
get_fields: function() {
let me = this;
return [
{
- fieldtype: 'MultiSelectList',
+ fieldtype: 'MultiSelectPills',
fieldname: 'assign_to',
label: __("Assign To"),
reqd: true,
get_data: function(txt) {
return frappe.db.get_link_options("User", txt, {user_type: "System User", enabled: 1});
- },
- onchange: () => me.set_assign_to_field_description()
+ }
},
{
label: __("Assign to me"),
@@ -242,9 +228,18 @@ frappe.ui.form.AssignToDialog = Class.extend({
fieldtype: 'Select',
fieldname: 'priority',
options: [
- { value: 'Low', label: __('Low') },
- { value: 'Medium', label: __('Medium') },
- { value: 'High', label: __('High') }
+ {
+ value: 'Low',
+ label: __('Low')
+ },
+ {
+ value: 'Medium',
+ label: __('Medium')
+ },
+ {
+ value: 'High',
+ label: __('High')
+ }
],
// Pick up priority from the source document, if it exists and is available in ToDo
default: ["Low", "Medium", "High"].includes(me.frm && me.frm.doc.priority ? me.frm.doc.priority : 'Medium')
From acc7de7335e28b13c5590b95a42ed972198de83b Mon Sep 17 00:00:00 2001
From: Shivam Mishra
Date: Fri, 17 Apr 2020 18:49:04 +0530
Subject: [PATCH 009/307] feat: added pandas date_range to utils
---
frappe/utils/dateutils.py | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/frappe/utils/dateutils.py b/frappe/utils/dateutils.py
index d5b7a3136b..907cab3d02 100644
--- a/frappe/utils/dateutils.py
+++ b/frappe/utils/dateutils.py
@@ -73,3 +73,9 @@ def datetime_in_user_format(date_time):
date_time = get_datetime(date_time)
from frappe.utils import formatdate
return formatdate(date_time.date()) + " " + date_time.strftime("%H:%M")
+
+def get_date_range(from_date, to_date, frequency="M", normalize=True):
+ from pandas import date_range
+ date_range = date_range(start=from_date, end=to_date, freq=frequency, normalize=normalize).to_pydatetime().tolist()
+
+ return date_range
\ No newline at end of file
From da6024242769e8c0934f8bc283ae8c9d93fbc573 Mon Sep 17 00:00:00 2001
From: Shivam Mishra
Date: Fri, 17 Apr 2020 18:49:12 +0530
Subject: [PATCH 010/307] feat: added website analytics report
---
frappe/website/report/__init__.py | 0
.../report/website_analytics/__init__.py | 0
.../website_analytics/website_analytics.js | 34 ++++
.../website_analytics/website_analytics.json | 27 ++++
.../website_analytics/website_analytics.py | 145 ++++++++++++++++++
5 files changed, 206 insertions(+)
create mode 100644 frappe/website/report/__init__.py
create mode 100644 frappe/website/report/website_analytics/__init__.py
create mode 100644 frappe/website/report/website_analytics/website_analytics.js
create mode 100644 frappe/website/report/website_analytics/website_analytics.json
create mode 100644 frappe/website/report/website_analytics/website_analytics.py
diff --git a/frappe/website/report/__init__.py b/frappe/website/report/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frappe/website/report/website_analytics/__init__.py b/frappe/website/report/website_analytics/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frappe/website/report/website_analytics/website_analytics.js b/frappe/website/report/website_analytics/website_analytics.js
new file mode 100644
index 0000000000..b607a16eb4
--- /dev/null
+++ b/frappe/website/report/website_analytics/website_analytics.js
@@ -0,0 +1,34 @@
+// Copyright (c) 2016, Frappe Technologies and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Website Analytics"] = {
+ "filters": [
+ {
+ fieldname: "from_date",
+ label: __("From Date"),
+ fieldtype: "Date",
+ default: frappe.datetime.add_days(frappe.datetime.now_date(true), -7),
+ reqd: 1
+ },
+ {
+ fieldname:"to_date",
+ label: __("To Date"),
+ fieldtype: "Date",
+ default: frappe.datetime.now_date(true),
+ reqd: 1
+ },
+ {
+ fieldname: "range",
+ label: __("Range"),
+ fieldtype: "Select",
+ options: [
+ { "value": "D", "label": __("Daily") },
+ { "value": "W", "label": __("Weekly") },
+ { "value": "M", "label": __("Monthly") },
+ ],
+ default: "D",
+ reqd: 1
+ }
+ ]
+};
diff --git a/frappe/website/report/website_analytics/website_analytics.json b/frappe/website/report/website_analytics/website_analytics.json
new file mode 100644
index 0000000000..62c5751a5c
--- /dev/null
+++ b/frappe/website/report/website_analytics/website_analytics.json
@@ -0,0 +1,27 @@
+{
+ "add_total_row": 0,
+ "creation": "2020-04-17 13:04:45.770148",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2020-04-17 16:10:30.168312",
+ "modified_by": "Administrator",
+ "module": "Website",
+ "name": "Website Analytics",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Web Page View",
+ "report_name": "Website Analytics",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "Website Manager"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/frappe/website/report/website_analytics/website_analytics.py b/frappe/website/report/website_analytics/website_analytics.py
new file mode 100644
index 0000000000..8b2d5b3806
--- /dev/null
+++ b/frappe/website/report/website_analytics/website_analytics.py
@@ -0,0 +1,145 @@
+# Copyright (c) 2013, Frappe Technologies and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.utils.dateutils import get_date_range
+
+def execute(filters=None):
+ return WebsiteAnalytics(filters).run()
+
+class WebsiteAnalytics(object):
+ def __init__(self, filters=None):
+ self.filters = frappe._dict(filters or {})
+ self.filters.to_date = frappe.utils.add_days(self.filters.to_date, 1)
+ self.query_filters = {'creation': ['between', [self.filters.from_date, self.filters.to_date]]}
+
+ def run(self):
+ columns = self.get_columns()
+ data = self.get_data()
+ summary = self.get_report_summary()
+ chart = self.get_chart_data()
+ return columns, data, None, chart, summary
+
+ def get_columns(self):
+ return [
+ {
+ "fieldname": "path",
+ "label": "Page",
+ "fieldtype": "Data",
+ "width": 300
+ },
+ {
+ "fieldname": "count",
+ "label": "Page Views",
+ "fieldtype": "Int",
+ "width": 150
+ }
+ ]
+
+ def get_data(self):
+ data = frappe.get_all("Web Page View", fields=['path', 'count(*) as count'], filters=self.query_filters, group_by="path", order_by='count desc')
+ return data
+
+ def get_chart_data(self):
+ def _get_field_for_chart(filters_range):
+ field = 'creation'
+ date_format = '%Y-%m-%d'
+
+ if filters_range == "W":
+ field = 'ADDDATE(creation, INTERVAL 1-DAYOFWEEK(creation) DAY)'
+
+ elif filters_range == "M":
+ date_format = '%Y-%m-01'
+
+ return field, date_format
+
+ field, date_format = _get_field_for_chart(self.filters.range)
+
+ data = frappe.db.sql("""
+ SELECT
+ DATE_FORMAT({0}, %s) as date,
+ COUNT(*) as count,
+ count(CASE WHEN is_unique = 1 THEN 1 END) as unique_count
+ FROM `tabWeb Page View`
+ WHERE creation BETWEEN %s AND %s
+ GROUP BY DATE_FORMAT({0}, %s)
+ ORDER BY creation
+ """.format(field), (date_format, self.filters.from_date, self.filters.to_date, date_format), as_dict=1, debug=1)
+
+ return self.prepare_chart_data(data)
+
+ def prepare_chart_data(self, data):
+ date_range = get_date_range(self.filters.from_date, self.filters.to_date, self.filters.range)
+ if self.filters.range == "M":
+ date_range = [frappe.utils.add_days(dd, 1) for dd in date_range]
+
+ labels = []
+ total_dataset = []
+ unique_dataset = []
+
+ def get_data_for_date(date):
+ for item in data:
+ item_date = frappe.utils.get_datetime(item.get("date")).date()
+ if item_date == date.date():
+ return item
+ return {'count': 0, 'unique_count': 0}
+
+
+ for date in date_range:
+ labels.append(date.strftime("%b %d %Y"))
+ match = get_data_for_date(date)
+ total_dataset.append(match.get('count', 0))
+ unique_dataset.append(match.get('unique_count', 0))
+
+ chart = {
+ "data": {
+ 'labels': labels,
+ 'datasets': [
+ {
+ 'name': "Total Views",
+ 'type': 'line',
+ 'values': total_dataset
+ },
+ {
+ 'name': "Unique Visits",
+ 'type': 'line',
+ 'values': unique_dataset
+ }
+ ]
+ },
+ "type": "axis-mixed",
+ 'lineOptions': {
+ 'regionFill': 1,
+ },
+ 'axisOptions': {
+ 'xIsSeries': 1
+ }
+ }
+
+ return chart
+
+
+ def get_report_summary(self):
+ summary_data = frappe.get_all("Web Page View", fields=['is_unique', 'count(*) as count'], filters=self.query_filters, group_by="is_unique")
+
+ total_count = 0
+ unique_count = 0
+ for data in summary_data:
+ if data.get('is_unique'):
+ unique_count = data.get('count')
+ total_count += data.get('count')
+ report_summary = [
+ {
+ "value": total_count,
+ "label": "Total Page Views",
+ "datatype": "Int",
+ },
+ {
+ "value": unique_count,
+ "label": "Unique Page Views",
+ "datatype": "Int",
+ },
+
+ ]
+ return report_summary
\ No newline at end of file
From 9b185802aaab09aa84dff1fce76292ea1edcdc54 Mon Sep 17 00:00:00 2001
From: prssanna
Date: Mon, 27 Apr 2020 18:56:12 +0530
Subject: [PATCH 011/307] fix: fix calculation of dates and values for
dashboard charts
---
.../dashboard_chart/dashboard_chart.py | 108 ++++--------------
.../dashboard_chart/test_dashboard_chart.py | 58 +++++++---
2 files changed, 64 insertions(+), 102 deletions(-)
diff --git a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py
index 7bed8f4504..4502748504 100644
--- a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py
+++ b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py
@@ -128,7 +128,6 @@ def get_chart_config(chart, filters, timespan, timegrain, from_date, to_date):
to_date = datetime.datetime.now()
doctype = chart.document_type
- unit_function = get_unit_function(doctype, chart.based_on, timegrain)
datefield = chart.based_on
aggregate_function = get_aggregate_function(chart.chart_type)
value_field = chart.value_based_on or '1'
@@ -141,23 +140,18 @@ def get_chart_config(chart, filters, timespan, timegrain, from_date, to_date):
data = frappe.db.get_all(
doctype,
fields = [
- 'extract(year from `tab{doctype}`.{datefield}) as _year'.format(doctype=doctype, datefield=datefield),
- '{} as _unit'.format(unit_function),
+ '{} as _unit'.format(datefield),
'{aggregate_function}({value_field})'.format(aggregate_function=aggregate_function, value_field=value_field),
],
filters = filters,
- group_by = '_year, _unit',
- order_by = '_year asc, _unit asc',
+ group_by = '_unit',
+ order_by = '_unit asc',
as_list = True,
ignore_ifnull = True
)
+ result = get_result(data, timegrain, from_date, to_date)
- # result given as year, unit -> convert it to end of period of that unit
- result = convert_to_dates(data, timegrain)
-
- # add missing data points for periods where there was no result
- result = add_missing_values(result, timegrain, timespan, from_date, to_date)
chart_config = {
"labels": [formatdate(r[0].strftime('%Y-%m-%d')) for r in result],
"datasets": [{
@@ -217,75 +211,22 @@ def get_aggregate_function(chart_type):
}[chart_type]
-def convert_to_dates(data, timegrain):
- """ Converts individual dates within data to the end of period """
- result = []
- for d in data:
- if d[2] != 0:
- if timegrain == 'Daily':
- result.append([add_to_date('{:d}-01-01'.format(int(d[0])), days = d[1] - 1), d[2]])
- elif timegrain == 'Weekly':
- result.append([add_to_date(add_to_date('{:d}-01-01'.format(int(d[0])), weeks = d[1] + 1), days = -1), d[2]])
- elif timegrain == 'Monthly':
- result.append([add_to_date(add_to_date('{:d}-01-01'.format(int(d[0])), months=d[1]), days = -1), d[2]])
- elif timegrain == 'Quarterly':
- result.append([add_to_date(add_to_date('{:d}-01-01'.format(int(d[0])), months=d[1] * 3), days = -1), d[2]])
- elif timegrain == 'Yearly':
- result.append([add_to_date(add_to_date('{:d}-01-01'.format(int(d[0])), months=12), days = -1), d[2]])
- result[-1][0] = getdate(result[-1][0])
-
- return result
-
-def get_unit_function(doctype, datefield, timegrain):
- unit_function = ''
- if timegrain=='Daily':
- if frappe.db.db_type == 'mariadb':
- unit_function = 'dayofyear(`tab{doctype}`.{datefield})'.format(
- doctype=doctype, datefield=datefield)
- else:
- unit_function = 'extract(doy from `tab{doctype}`.{datefield})'.format(
- doctype=doctype, datefield=datefield)
-
- else:
- unit_function = 'extract({unit} from `tab{doctype}`.{datefield})'.format(
- unit = timegrain[:-2].lower(), doctype=doctype, datefield=datefield)
-
- return unit_function
-
-def add_missing_values(data, timegrain, timespan, from_date, to_date):
- # add missing intervals
+def get_result(data, timegrain, from_date, to_date):
+ start_date = getdate(from_date)
+ end_date = getdate(to_date)
result = []
- if timespan != 'All Time':
- first_expected_date = get_period_ending(from_date, timegrain)
- # fill out data before the first data point
- first_data_point_date = data[0][0] if data else getdate(add_to_date(to_date, days=1))
- while first_data_point_date > first_expected_date:
- result.append([first_expected_date, 0.0])
- first_expected_date = get_next_expected_date(first_expected_date, timegrain)
+ while start_date <= end_date:
+ next_date = get_next_expected_date(start_date, timegrain)
+ result.append([next_date, 0.0])
+ start_date = next_date
- # fill data points and missing points
- for i, d in enumerate(data):
- result.append(d)
-
- next_expected_date = get_next_expected_date(d[0], timegrain)
-
- if i < len(data)-1:
- next_date = data[i+1][0]
- else:
- # already reached at end of data, see if we need any more dates
- next_date = getdate(nowdate())
-
- # if next data point is earler than the expected date
- # need to fill out missing data points
- while next_date > next_expected_date:
- # fill missing value
- result.append([next_expected_date, 0.0])
- next_expected_date = get_next_expected_date(next_expected_date, timegrain)
-
- # add date for the last period (if missing)
- if result and get_period_ending(to_date, timegrain) > result[-1][0]:
- result.append([get_period_ending(to_date, timegrain), 0.0])
+ data_index = 0
+ if data:
+ for i, d in enumerate(result):
+ while data_index < len(data) and getdate(data[data_index][0]) <= d[0]:
+ d[1] += data[data_index][1]
+ data_index += 1
return result
@@ -314,17 +255,12 @@ def get_period_ending(date, timegrain):
return getdate(date)
def get_week_ending(date):
- # fun fact: week ends on the day before 1st Jan of the year.
- # for 2019 it is Monday
+ # week starts on monday
+ from datetime import timedelta
+ start = date - timedelta(days = date.weekday())
+ end = start + timedelta(days=6)
- week_of_the_year = int(date.strftime('%U'))
-
- if week_of_the_year == 52:
- date = add_to_date(date, years=1)
- # first day of next week
- date = add_to_date('{}-01-01'.format(date.year), weeks = (week_of_the_year%52) + 1)
- # last day of this week
- return add_to_date(date, days=-1)
+ return end
def get_month_ending(date):
month_of_the_year = int(date.strftime('%m'))
diff --git a/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py
index 4425c4fd45..dfc6edbf58 100644
--- a/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py
+++ b/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py
@@ -17,10 +17,9 @@ class TestDashboardChart(unittest.TestCase):
self.assertEqual(get_period_ending('2019-04-10', 'Daily'),
getdate('2019-04-10'))
- # fun fact: week ends on the day before 1st Jan of the year.
- # for 2019 it is Monday
+ # week starts on monday
self.assertEqual(get_period_ending('2019-04-10', 'Weekly'),
- getdate('2019-04-15'))
+ getdate('2019-04-14'))
self.assertEqual(get_period_ending('2019-04-10', 'Monthly'),
getdate('2019-04-30'))
@@ -133,6 +132,34 @@ class TestDashboardChart(unittest.TestCase):
frappe.db.rollback()
+ def test_weekly_dashboard_chart(self):
+ insert_test_records()
+
+ if frappe.db.exists('Dashboard Chart', 'Test Weekly Dashboard Chart'):
+ frappe.delete_doc('Dashboard Chart', 'Test Weekly Dashboard Chart')
+
+ frappe.get_doc(dict(
+ doctype = 'Dashboard Chart',
+ chart_name = 'Test Weekly Dashboard Chart',
+ chart_type = 'Sum',
+ document_type = 'Communication',
+ based_on = 'communication_date',
+ value_based_on = 'rating',
+ timespan = 'Select Date Range',
+ time_interval = 'Weekly',
+ from_date = datetime(2018, 12, 30),
+ to_date = datetime(2019, 1, 15),
+ filters_json = '[]',
+ timeseries = 1
+ )).insert()
+
+ result = get(chart_name ='Test Weekly Dashboard Chart', refresh = 1)
+
+ self.assertEqual(result.get('datasets')[0].get('values'), [200.0, 400.0, 0.0])
+ self.assertEqual(result.get('labels'), [formatdate('2019-01-06'), formatdate('2019-01-13'), formatdate('2019-01-20')])
+
+ frappe.db.rollback()
+
def test_group_by_chart_type(self):
if frappe.db.exists('Dashboard Chart', 'Test Group By Dashboard Chart'):
frappe.delete_doc('Dashboard Chart', 'Test Group By Dashboard Chart')
@@ -155,17 +182,16 @@ class TestDashboardChart(unittest.TestCase):
frappe.db.rollback()
- def test_dashboard_with_single_doctype(self):
- if frappe.db.exists('Dashboard Chart', 'Test Single DocType In Dashboard Chart'):
- frappe.delete_doc('Dashboard Chart', 'Test Single DocType In Dashboard Chart')
+def insert_test_records():
+ create_new_communication(datetime(2019, 1, 10), 100)
+ create_new_communication(datetime(2019, 1, 6), 200)
+ create_new_communication(datetime(2019, 1, 8), 300)
- chart_doc = frappe.get_doc(dict(
- doctype = 'Dashboard Chart',
- chart_name = 'Test Single DocType In Dashboard Chart',
- chart_type = 'Count',
- document_type = 'System Settings',
- group_by_based_on = 'Created On',
- filters_json = '{}',
- ))
-
- self.assertRaises(frappe.ValidationError, chart_doc.insert)
+def create_new_communication(date, rating):
+ communication = {
+ 'doctype': 'Communication',
+ 'subject': 'Test Communication',
+ 'rating': rating,
+ 'communication_date': date
+ }
+ frappe.get_doc(communication).insert()
From 19dc0a65b06e75def4d5b755eefb00eb805c64ab Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Fri, 13 Mar 2020 17:16:52 +0530
Subject: [PATCH 012/307] feat: initial bingup for cutomization export
---
.../doctype/customization_export/__init__.py | 0
.../customization_export.json | 56 +++++++++++++
.../customization_export.py | 10 +++
.../doctype/manage_customization/__init__.py | 0
.../manage_customization.js | 46 +++++++++++
.../manage_customization.json | 73 +++++++++++++++++
.../manage_customization.py | 78 +++++++++++++++++++
.../test_manage_customization.py | 10 +++
8 files changed, 273 insertions(+)
create mode 100644 frappe/custom/doctype/customization_export/__init__.py
create mode 100644 frappe/custom/doctype/customization_export/customization_export.json
create mode 100644 frappe/custom/doctype/customization_export/customization_export.py
create mode 100644 frappe/custom/doctype/manage_customization/__init__.py
create mode 100644 frappe/custom/doctype/manage_customization/manage_customization.js
create mode 100644 frappe/custom/doctype/manage_customization/manage_customization.json
create mode 100644 frappe/custom/doctype/manage_customization/manage_customization.py
create mode 100644 frappe/custom/doctype/manage_customization/test_manage_customization.py
diff --git a/frappe/custom/doctype/customization_export/__init__.py b/frappe/custom/doctype/customization_export/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frappe/custom/doctype/customization_export/customization_export.json b/frappe/custom/doctype/customization_export/customization_export.json
new file mode 100644
index 0000000000..bc59a89f4f
--- /dev/null
+++ b/frappe/custom/doctype/customization_export/customization_export.json
@@ -0,0 +1,56 @@
+{
+ "actions": [],
+ "creation": "2020-03-12 14:51:09.260025",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "document_type",
+ "sb_00",
+ "filters",
+ "cb_00",
+ "or_filters"
+ ],
+ "fields": [
+ {
+ "fieldname": "document_type",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Document Type",
+ "options": "DocType",
+ "reqd": 1
+ },
+ {
+ "fieldname": "filters",
+ "fieldtype": "Code",
+ "in_list_view": 1,
+ "label": "Filters"
+ },
+ {
+ "fieldname": "or_filters",
+ "fieldtype": "Code",
+ "in_list_view": 1,
+ "label": "Or Filters"
+ },
+ {
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "cb_00",
+ "fieldtype": "Column Break"
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-03-13 16:53:15.214275",
+ "modified_by": "Administrator",
+ "module": "Custom",
+ "name": "Customization Export",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/frappe/custom/doctype/customization_export/customization_export.py b/frappe/custom/doctype/customization_export/customization_export.py
new file mode 100644
index 0000000000..70a7da3b08
--- /dev/null
+++ b/frappe/custom/doctype/customization_export/customization_export.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class CustomizationExport(Document):
+ pass
diff --git a/frappe/custom/doctype/manage_customization/__init__.py b/frappe/custom/doctype/manage_customization/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frappe/custom/doctype/manage_customization/manage_customization.js b/frappe/custom/doctype/manage_customization/manage_customization.js
new file mode 100644
index 0000000000..41e2fd316b
--- /dev/null
+++ b/frappe/custom/doctype/manage_customization/manage_customization.js
@@ -0,0 +1,46 @@
+// Copyright (c) 2020, Frappe Technologies and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Manage Customization', {
+ refresh: function(frm) {
+ frappe.realtime.on("exporting_progress", (data) => {
+ if (data.progress !== data.total) {
+ frm.dashboard.show_progress("Exporting", data.progress / data.total * 100, __("{0}", [data.message]));
+ } else {
+ frm.dashboard.hide_progress();
+ }
+ });
+
+ frappe.realtime.on("importing_progress", (data) => {
+ if (data.progress !== data.total) {
+ frm.dashboard.show_progress("Importing", data.progress / data.total * 100, __("{0}", [data.message]));
+ } else {
+ frm.dashboard.hide_progress();
+ }
+ });
+ },
+ export: function(frm) {
+ frappe.call({
+ method: 'frappe.custom.doctype.manage_customization.manage_customization.export_customizations',
+ callback: function(r) {
+ if (r.message) {
+ const args = {
+ cmd: 'frappe.custom.doctype.manage_customization.manage_customization.export_customizations',
+ data: r.message.data
+ };
+ open_url_post(frappe.request.url, args);
+ }
+ }
+ });
+ },
+ import: function(frm) {
+ frappe.call({
+ method: 'frappe.custom.doctype.manage_customization.manage_customization.import_customizations',
+ callback: function(r) {
+ if (r.message) {
+ console.log("done")
+ }
+ }
+ });
+ }
+});
diff --git a/frappe/custom/doctype/manage_customization/manage_customization.json b/frappe/custom/doctype/manage_customization/manage_customization.json
new file mode 100644
index 0000000000..43c4596590
--- /dev/null
+++ b/frappe/custom/doctype/manage_customization/manage_customization.json
@@ -0,0 +1,73 @@
+{
+ "actions": [],
+ "creation": "2020-03-01 23:21:17.394500",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "sb_00",
+ "export_customization",
+ "export",
+ "sb_01",
+ "import_customization",
+ "import"
+ ],
+ "fields": [
+ {
+ "fieldname": "export_customization",
+ "fieldtype": "Table",
+ "label": "Customizations to Export",
+ "options": "Customization Export"
+ },
+ {
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break",
+ "label": "Export Customizations"
+ },
+ {
+ "fieldname": "sb_01",
+ "fieldtype": "Section Break",
+ "label": "Import Customizations"
+ },
+ {
+ "fieldname": "import_customization",
+ "fieldtype": "Attach",
+ "label": "Attach"
+ },
+ {
+ "depends_on": "export_customization",
+ "fieldname": "export",
+ "fieldtype": "Button",
+ "label": "Export"
+ },
+ {
+ "depends_on": "import_customization",
+ "fieldname": "import",
+ "fieldtype": "Button",
+ "label": "Import"
+ }
+ ],
+ "issingle": 1,
+ "links": [],
+ "modified": "2020-03-13 17:14:00.382402",
+ "modified_by": "Administrator",
+ "module": "Custom",
+ "name": "Manage Customization",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/frappe/custom/doctype/manage_customization/manage_customization.py b/frappe/custom/doctype/manage_customization/manage_customization.py
new file mode 100644
index 0000000000..3e21b587c9
--- /dev/null
+++ b/frappe/custom/doctype/manage_customization/manage_customization.py
@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+import json
+
+class ManageCustomization(Document):
+ pass
+
+@frappe.whitelist()
+def export_customizations():
+ """Export fixtures as JSON"""
+
+ export_customizations_doc = frappe.get_single("Manage Customization")
+ customizations = []
+
+ for doctype in export_customizations_doc.export_customization:
+ filters, or_filters = {}, {}
+
+ if doctype.get("filters"):
+ filters = json.loads(doctype.get("filters"))
+ if doctype.get("or_filters"):
+ or_filters = json.loads(doctype.get("or_filters"))
+
+ docs = frappe.get_all(doctype.get("document_type"), filters=filters, or_filters=or_filters)
+ length = len(docs)
+ for idx, doc in enumerate(docs):
+ frappe.publish_realtime("exporting_progress", dict(progress=idx, total=length, message=doctype.get("document_type")), user=frappe.session.user)
+ customizations.append(frappe.get_doc(doctype.get("document_type"), doc.name).as_dict())
+
+ return frappe._dict({
+ "data": post_process(customizations)
+ })
+
+@frappe.whitelist()
+def import_customizations():
+ """Import fixtures as JSON"""
+
+ import_customizations_doc = frappe.get_single("Manage Customization")
+
+ with open(frappe.utils.get_url() + import_customizations_doc.import_customization, 'r') as f:
+ f = json.loads(f)
+
+ length = f.get("data")
+
+ for idx, doc in enumerate(f.get("data")):
+ frappe.publish_realtime("exporting_progress", dict(progress=idx, total=length, message=doc.get("doctype")), user=frappe.session.user)
+ frappe.get_doc(doc).insert(ignore_permissions=True)
+
+def post_process(customizations):
+ del_keys = ('modified_by', 'creation', 'owner', 'idx', 'name', 'modified', 'docstatus')
+
+ for doc in customizations:
+ for key in del_keys:
+ if key in doc:
+ del doc[key]
+
+ for key, value in doc.items():
+ if not isinstance(value, list):
+ continue
+
+ for child in value:
+ for key in del_keys:
+ if key in child:
+ del child[key]
+
+ return customizations
+
+@frappe.whitelist()
+def download_customization_json():
+ data = frappe._dict(frappe.local.form_dict)
+ frappe.response['filename'] = 'Customizations.json'
+ frappe.response['filecontent'] = data.get("data")
+ frappe.response['content_type'] = 'application/json'
+ frappe.response['type'] = 'download'
\ No newline at end of file
diff --git a/frappe/custom/doctype/manage_customization/test_manage_customization.py b/frappe/custom/doctype/manage_customization/test_manage_customization.py
new file mode 100644
index 0000000000..af1a332bb4
--- /dev/null
+++ b/frappe/custom/doctype/manage_customization/test_manage_customization.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestManageCustomization(unittest.TestCase):
+ pass
From eb57ec7903cbd5dc58e5deb8281f850d37d3f327 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Fri, 13 Mar 2020 18:21:14 +0530
Subject: [PATCH 013/307] fix: importer for customization fix
---
.../manage_customization.js | 6 ++----
.../manage_customization.py | 18 +++++++++++-------
2 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/frappe/custom/doctype/manage_customization/manage_customization.js b/frappe/custom/doctype/manage_customization/manage_customization.js
index 41e2fd316b..418a7c2c17 100644
--- a/frappe/custom/doctype/manage_customization/manage_customization.js
+++ b/frappe/custom/doctype/manage_customization/manage_customization.js
@@ -36,10 +36,8 @@ frappe.ui.form.on('Manage Customization', {
import: function(frm) {
frappe.call({
method: 'frappe.custom.doctype.manage_customization.manage_customization.import_customizations',
- callback: function(r) {
- if (r.message) {
- console.log("done")
- }
+ callback: function() {
+ frappe.msgprint(__("Customizations Imported."));
}
});
}
diff --git a/frappe/custom/doctype/manage_customization/manage_customization.py b/frappe/custom/doctype/manage_customization/manage_customization.py
index 3e21b587c9..feb140251a 100644
--- a/frappe/custom/doctype/manage_customization/manage_customization.py
+++ b/frappe/custom/doctype/manage_customization/manage_customization.py
@@ -39,16 +39,20 @@ def export_customizations():
def import_customizations():
"""Import fixtures as JSON"""
- import_customizations_doc = frappe.get_single("Manage Customization")
+ import_file = frappe.get_all("File", filters={
+ "attached_to_doctype": "Manage Customization",
+ "attached_to_name": "Manage Customization"
+ }, limit=1, order_by="creation desc")
- with open(frappe.utils.get_url() + import_customizations_doc.import_customization, 'r') as f:
- f = json.loads(f)
+ if not import_file:
+ return
- length = f.get("data")
+ content = json.loads(frappe.get_doc("File", import_file[0].name).get_content())
+ length = len(content)
- for idx, doc in enumerate(f.get("data")):
- frappe.publish_realtime("exporting_progress", dict(progress=idx, total=length, message=doc.get("doctype")), user=frappe.session.user)
- frappe.get_doc(doc).insert(ignore_permissions=True)
+ for idx, doc in enumerate(content.get("message").get("data")):
+ frappe.publish_realtime("exporting_progress", dict(progress=idx, total=length, message=doc.get("doctype")), user=frappe.session.user)
+ frappe.get_doc(doc).insert(ignore_permissions=True)
def post_process(customizations):
del_keys = ('modified_by', 'creation', 'owner', 'idx', 'name', 'modified', 'docstatus')
From 846594d6c8516a9ed89ec73404b47cc46d5936a8 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Fri, 13 Mar 2020 18:41:36 +0530
Subject: [PATCH 014/307] fix: miscellaneous fixes
---
.../custom/doctype/manage_customization/manage_customization.js | 2 +-
.../custom/doctype/manage_customization/manage_customization.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/frappe/custom/doctype/manage_customization/manage_customization.js b/frappe/custom/doctype/manage_customization/manage_customization.js
index 418a7c2c17..4c86519dd8 100644
--- a/frappe/custom/doctype/manage_customization/manage_customization.js
+++ b/frappe/custom/doctype/manage_customization/manage_customization.js
@@ -28,7 +28,7 @@ frappe.ui.form.on('Manage Customization', {
cmd: 'frappe.custom.doctype.manage_customization.manage_customization.export_customizations',
data: r.message.data
};
- open_url_post(frappe.request.url, args);
+ open_url_post(frappe.request.url, args, true);
}
}
});
diff --git a/frappe/custom/doctype/manage_customization/manage_customization.py b/frappe/custom/doctype/manage_customization/manage_customization.py
index feb140251a..f3c18d5017 100644
--- a/frappe/custom/doctype/manage_customization/manage_customization.py
+++ b/frappe/custom/doctype/manage_customization/manage_customization.py
@@ -52,7 +52,7 @@ def import_customizations():
for idx, doc in enumerate(content.get("message").get("data")):
frappe.publish_realtime("exporting_progress", dict(progress=idx, total=length, message=doc.get("doctype")), user=frappe.session.user)
- frappe.get_doc(doc).insert(ignore_permissions=True)
+ frappe.get_doc(doc).insert(ignore_permissions=True, ignore_if_duplicate=True)
def post_process(customizations):
del_keys = ('modified_by', 'creation', 'owner', 'idx', 'name', 'modified', 'docstatus')
From b3f45bd81c81747713359bab032b962c4d166fac Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Sat, 14 Mar 2020 11:59:13 +0530
Subject: [PATCH 015/307] feat: rename to package
---
frappe/config/customization.py | 8 +--
.../__init__.py | 0
.../package.js} | 18 +++---
.../package.json} | 58 +++++++++++--------
.../package.py} | 44 +++++++-------
.../test_package.py} | 2 +-
.../__init__.py | 0
.../package_doctype.json} | 22 +++----
.../package_doctype.py} | 2 +-
9 files changed, 82 insertions(+), 72 deletions(-)
rename frappe/custom/doctype/{customization_export => package}/__init__.py (100%)
rename frappe/custom/doctype/{manage_customization/manage_customization.js => package/package.js} (56%)
rename frappe/custom/doctype/{manage_customization/manage_customization.json => package/package.json} (63%)
rename frappe/custom/doctype/{manage_customization/manage_customization.py => package/package.py} (55%)
rename frappe/custom/doctype/{manage_customization/test_manage_customization.py => package/test_package.py} (78%)
rename frappe/custom/doctype/{manage_customization => package_doctype}/__init__.py (100%)
rename frappe/custom/doctype/{customization_export/customization_export.json => package_doctype/package_doctype.json} (88%)
rename frappe/custom/doctype/{customization_export/customization_export.py => package_doctype/package_doctype.py} (86%)
diff --git a/frappe/config/customization.py b/frappe/config/customization.py
index 06eaa2ea00..3d587e6839 100644
--- a/frappe/config/customization.py
+++ b/frappe/config/customization.py
@@ -3,7 +3,7 @@ from frappe import _
def get_data():
return [
- {
+ {
"label": _("Form Customization"),
"icon": "fa fa-glass",
"items": [
@@ -57,9 +57,9 @@ def get_data():
},
{
"type": "doctype",
- "label": _("Custom Tags"),
- "name": "Tag Category",
- "description": _("Add your own Tag Categories")
+ "label": _("Package"),
+ "name": "Package",
+ "description": _("Import and Export Packages.")
}
]
}
diff --git a/frappe/custom/doctype/customization_export/__init__.py b/frappe/custom/doctype/package/__init__.py
similarity index 100%
rename from frappe/custom/doctype/customization_export/__init__.py
rename to frappe/custom/doctype/package/__init__.py
diff --git a/frappe/custom/doctype/manage_customization/manage_customization.js b/frappe/custom/doctype/package/package.js
similarity index 56%
rename from frappe/custom/doctype/manage_customization/manage_customization.js
rename to frappe/custom/doctype/package/package.js
index 4c86519dd8..c362c51b24 100644
--- a/frappe/custom/doctype/manage_customization/manage_customization.js
+++ b/frappe/custom/doctype/package/package.js
@@ -1,18 +1,18 @@
// Copyright (c) 2020, Frappe Technologies and contributors
// For license information, please see license.txt
-frappe.ui.form.on('Manage Customization', {
+frappe.ui.form.on('Package', {
refresh: function(frm) {
- frappe.realtime.on("exporting_progress", (data) => {
- if (data.progress !== data.total) {
+ frappe.realtime.on("exporting_package", (data) => {
+ if (data.progress !== (data.total-1)) {
frm.dashboard.show_progress("Exporting", data.progress / data.total * 100, __("{0}", [data.message]));
} else {
frm.dashboard.hide_progress();
}
});
- frappe.realtime.on("importing_progress", (data) => {
- if (data.progress !== data.total) {
+ frappe.realtime.on("importing_package", (data) => {
+ if (data.progress !== (data.total-1)) {
frm.dashboard.show_progress("Importing", data.progress / data.total * 100, __("{0}", [data.message]));
} else {
frm.dashboard.hide_progress();
@@ -21,11 +21,11 @@ frappe.ui.form.on('Manage Customization', {
},
export: function(frm) {
frappe.call({
- method: 'frappe.custom.doctype.manage_customization.manage_customization.export_customizations',
+ method: 'frappe.custom.doctype.package.package.export_package',
callback: function(r) {
if (r.message) {
const args = {
- cmd: 'frappe.custom.doctype.manage_customization.manage_customization.export_customizations',
+ cmd: 'frappe.custom.doctype.package.package.download_package',
data: r.message.data
};
open_url_post(frappe.request.url, args, true);
@@ -35,9 +35,9 @@ frappe.ui.form.on('Manage Customization', {
},
import: function(frm) {
frappe.call({
- method: 'frappe.custom.doctype.manage_customization.manage_customization.import_customizations',
+ method: 'frappe.custom.doctype.package.package.import_package',
callback: function() {
- frappe.msgprint(__("Customizations Imported."));
+ frappe.msgprint(__("Package Imported."));
}
});
}
diff --git a/frappe/custom/doctype/manage_customization/manage_customization.json b/frappe/custom/doctype/package/package.json
similarity index 63%
rename from frappe/custom/doctype/manage_customization/manage_customization.json
rename to frappe/custom/doctype/package/package.json
index 43c4596590..cad2ca6788 100644
--- a/frappe/custom/doctype/manage_customization/manage_customization.json
+++ b/frappe/custom/doctype/package/package.json
@@ -1,58 +1,58 @@
{
"actions": [],
- "creation": "2020-03-01 23:21:17.394500",
+ "creation": "2020-03-14 11:20:14.850552",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"sb_00",
- "export_customization",
+ "export_package",
"export",
"sb_01",
- "import_customization",
+ "import_package",
"import"
],
"fields": [
- {
- "fieldname": "export_customization",
- "fieldtype": "Table",
- "label": "Customizations to Export",
- "options": "Customization Export"
- },
{
"fieldname": "sb_00",
"fieldtype": "Section Break",
- "label": "Export Customizations"
+ "label": "Export Package"
},
{
- "fieldname": "sb_01",
- "fieldtype": "Section Break",
- "label": "Import Customizations"
- },
- {
- "fieldname": "import_customization",
- "fieldtype": "Attach",
- "label": "Attach"
- },
- {
- "depends_on": "export_customization",
+ "depends_on": "export_package",
"fieldname": "export",
"fieldtype": "Button",
"label": "Export"
},
{
- "depends_on": "import_customization",
+ "fieldname": "sb_01",
+ "fieldtype": "Section Break",
+ "label": "Import Package"
+ },
+ {
+ "depends_on": "import_package",
"fieldname": "import",
"fieldtype": "Button",
"label": "Import"
+ },
+ {
+ "fieldname": "export_package",
+ "fieldtype": "Table",
+ "label": "Package",
+ "options": "Package DocType"
+ },
+ {
+ "fieldname": "import_package",
+ "fieldtype": "Attach",
+ "label": "Attach"
}
],
"issingle": 1,
"links": [],
- "modified": "2020-03-13 17:14:00.382402",
+ "modified": "2020-03-14 11:52:58.221081",
"modified_by": "Administrator",
"module": "Custom",
- "name": "Manage Customization",
+ "name": "Package",
"owner": "Administrator",
"permissions": [
{
@@ -64,6 +64,16 @@
"role": "System Manager",
"share": 1,
"write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "role": "All",
+ "share": 1,
+ "write": 1
}
],
"quick_entry": 1,
diff --git a/frappe/custom/doctype/manage_customization/manage_customization.py b/frappe/custom/doctype/package/package.py
similarity index 55%
rename from frappe/custom/doctype/manage_customization/manage_customization.py
rename to frappe/custom/doctype/package/package.py
index f3c18d5017..e3a29144d9 100644
--- a/frappe/custom/doctype/manage_customization/manage_customization.py
+++ b/frappe/custom/doctype/package/package.py
@@ -7,17 +7,17 @@ import frappe
from frappe.model.document import Document
import json
-class ManageCustomization(Document):
+class Package(Document):
pass
@frappe.whitelist()
-def export_customizations():
- """Export fixtures as JSON"""
+def export_package():
+ """Export package as JSON"""
- export_customizations_doc = frappe.get_single("Manage Customization")
- customizations = []
+ package_doc = frappe.get_single("Package")
+ package = []
- for doctype in export_customizations_doc.export_customization:
+ for doctype in package_doc.export_package:
filters, or_filters = {}, {}
if doctype.get("filters"):
@@ -28,36 +28,36 @@ def export_customizations():
docs = frappe.get_all(doctype.get("document_type"), filters=filters, or_filters=or_filters)
length = len(docs)
for idx, doc in enumerate(docs):
- frappe.publish_realtime("exporting_progress", dict(progress=idx, total=length, message=doctype.get("document_type")), user=frappe.session.user)
- customizations.append(frappe.get_doc(doctype.get("document_type"), doc.name).as_dict())
+ frappe.publish_realtime("exporting_package", dict(progress=idx, total=length, message=doctype.get("document_type")), user=frappe.session.user)
+ package.append(frappe.get_doc(doctype.get("document_type"), doc.name).as_dict())
return frappe._dict({
- "data": post_process(customizations)
+ "data": post_process(package)
})
@frappe.whitelist()
-def import_customizations():
- """Import fixtures as JSON"""
+def import_package():
+ """Import package from JSON"""
- import_file = frappe.get_all("File", filters={
- "attached_to_doctype": "Manage Customization",
- "attached_to_name": "Manage Customization"
+ package_file = frappe.get_all("File", filters={
+ "attached_to_doctype": "Package",
+ "attached_to_name": "Package"
}, limit=1, order_by="creation desc")
- if not import_file:
+ if not package_file:
return
- content = json.loads(frappe.get_doc("File", import_file[0].name).get_content())
+ content = json.loads(frappe.get_doc("File", package_file[0].name).get_content())
length = len(content)
for idx, doc in enumerate(content.get("message").get("data")):
- frappe.publish_realtime("exporting_progress", dict(progress=idx, total=length, message=doc.get("doctype")), user=frappe.session.user)
+ frappe.publish_realtime("importing_package", dict(progress=idx, total=length, message=doc.get("doctype")), user=frappe.session.user)
frappe.get_doc(doc).insert(ignore_permissions=True, ignore_if_duplicate=True)
-def post_process(customizations):
+def post_process(package):
del_keys = ('modified_by', 'creation', 'owner', 'idx', 'name', 'modified', 'docstatus')
- for doc in customizations:
+ for doc in package:
for key in del_keys:
if key in doc:
del doc[key]
@@ -71,12 +71,12 @@ def post_process(customizations):
if key in child:
del child[key]
- return customizations
+ return package
@frappe.whitelist()
-def download_customization_json():
+def download_package():
data = frappe._dict(frappe.local.form_dict)
- frappe.response['filename'] = 'Customizations.json'
+ frappe.response['filename'] = 'Package.json'
frappe.response['filecontent'] = data.get("data")
frappe.response['content_type'] = 'application/json'
frappe.response['type'] = 'download'
\ No newline at end of file
diff --git a/frappe/custom/doctype/manage_customization/test_manage_customization.py b/frappe/custom/doctype/package/test_package.py
similarity index 78%
rename from frappe/custom/doctype/manage_customization/test_manage_customization.py
rename to frappe/custom/doctype/package/test_package.py
index af1a332bb4..3a17d51260 100644
--- a/frappe/custom/doctype/manage_customization/test_manage_customization.py
+++ b/frappe/custom/doctype/package/test_package.py
@@ -6,5 +6,5 @@ from __future__ import unicode_literals
# import frappe
import unittest
-class TestManageCustomization(unittest.TestCase):
+class TestPackage(unittest.TestCase):
pass
diff --git a/frappe/custom/doctype/manage_customization/__init__.py b/frappe/custom/doctype/package_doctype/__init__.py
similarity index 100%
rename from frappe/custom/doctype/manage_customization/__init__.py
rename to frappe/custom/doctype/package_doctype/__init__.py
diff --git a/frappe/custom/doctype/customization_export/customization_export.json b/frappe/custom/doctype/package_doctype/package_doctype.json
similarity index 88%
rename from frappe/custom/doctype/customization_export/customization_export.json
rename to frappe/custom/doctype/package_doctype/package_doctype.json
index bc59a89f4f..cfc4cbbe8f 100644
--- a/frappe/custom/doctype/customization_export/customization_export.json
+++ b/frappe/custom/doctype/package_doctype/package_doctype.json
@@ -1,6 +1,6 @@
{
"actions": [],
- "creation": "2020-03-12 14:51:09.260025",
+ "creation": "2020-03-14 11:20:42.875446",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
@@ -20,33 +20,33 @@
"options": "DocType",
"reqd": 1
},
+ {
+ "fieldname": "sb_00",
+ "fieldtype": "Section Break"
+ },
{
"fieldname": "filters",
"fieldtype": "Code",
"in_list_view": 1,
"label": "Filters"
},
+ {
+ "fieldname": "cb_00",
+ "fieldtype": "Column Break"
+ },
{
"fieldname": "or_filters",
"fieldtype": "Code",
"in_list_view": 1,
"label": "Or Filters"
- },
- {
- "fieldname": "sb_00",
- "fieldtype": "Section Break"
- },
- {
- "fieldname": "cb_00",
- "fieldtype": "Column Break"
}
],
"istable": 1,
"links": [],
- "modified": "2020-03-13 16:53:15.214275",
+ "modified": "2020-03-14 11:20:42.875446",
"modified_by": "Administrator",
"module": "Custom",
- "name": "Customization Export",
+ "name": "Package DocType",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
diff --git a/frappe/custom/doctype/customization_export/customization_export.py b/frappe/custom/doctype/package_doctype/package_doctype.py
similarity index 86%
rename from frappe/custom/doctype/customization_export/customization_export.py
rename to frappe/custom/doctype/package_doctype/package_doctype.py
index 70a7da3b08..c185395965 100644
--- a/frappe/custom/doctype/customization_export/customization_export.py
+++ b/frappe/custom/doctype/package_doctype/package_doctype.py
@@ -6,5 +6,5 @@ from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
-class CustomizationExport(Document):
+class PackageDocType(Document):
pass
From 6aa5580eaee2bc6112d81a5d6be36dcc45a6ab35 Mon Sep 17 00:00:00 2001
From: Himanshu
Date: Sat, 14 Mar 2020 12:16:30 +0530
Subject: [PATCH 016/307] Update package.py
---
frappe/custom/doctype/package/package.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/frappe/custom/doctype/package/package.py b/frappe/custom/doctype/package/package.py
index e3a29144d9..e3b6468791 100644
--- a/frappe/custom/doctype/package/package.py
+++ b/frappe/custom/doctype/package/package.py
@@ -50,7 +50,7 @@ def import_package():
content = json.loads(frappe.get_doc("File", package_file[0].name).get_content())
length = len(content)
- for idx, doc in enumerate(content.get("message").get("data")):
+ for idx, doc in enumerate(content):
frappe.publish_realtime("importing_package", dict(progress=idx, total=length, message=doc.get("doctype")), user=frappe.session.user)
frappe.get_doc(doc).insert(ignore_permissions=True, ignore_if_duplicate=True)
@@ -79,4 +79,4 @@ def download_package():
frappe.response['filename'] = 'Package.json'
frappe.response['filecontent'] = data.get("data")
frappe.response['content_type'] = 'application/json'
- frappe.response['type'] = 'download'
\ No newline at end of file
+ frappe.response['type'] = 'download'
From ea93f12a9a8b5557b1bbcc90c1d656f577f680aa Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Mon, 16 Mar 2020 22:29:55 +0530
Subject: [PATCH 017/307] feat: use UI for adding filters
---
frappe/custom/doctype/package/package.js | 80 +++++++++++++++++++
frappe/custom/doctype/package/package.py | 29 +++----
.../package_doctype/package_doctype.json | 32 +++-----
3 files changed, 105 insertions(+), 36 deletions(-)
diff --git a/frappe/custom/doctype/package/package.js b/frappe/custom/doctype/package/package.js
index c362c51b24..08ec8ac96b 100644
--- a/frappe/custom/doctype/package/package.js
+++ b/frappe/custom/doctype/package/package.js
@@ -42,3 +42,83 @@ frappe.ui.form.on('Package', {
});
}
});
+
+frappe.ui.form.on('Package DocType', {
+ form_render: function (frm, cdt, cdn) {
+ function _show_filters(filters, table) {
+ table.find('tbody').empty();
+
+ if (filters.length > 0) {
+ filters.forEach(filter => {
+ const filter_row =
+ $(`
+ | ${filter[1]} |
+ ${filter[2] || ""} |
+ ${filter[3]} |
+
`);
+
+ table.find('tbody').append(filter_row);
+ });
+ } else {
+ const filter_row = $(`|
+ ${__("Click to Set Filters")} |
`);
+ table.find('tbody').append(filter_row);
+ }
+ }
+
+ let row = frappe.get_doc(cdt, cdn);
+
+ let wrapper = $(`[data-fieldname="filters_json"]`).empty();
+ let table = $(`
+
+
+ | ${__('Filter')} |
+ ${__('Condition')} |
+ ${__('Value')} |
+
+
+
+
+
`).appendTo(wrapper);
+ $(`${__("Click table to edit")}
`).appendTo(wrapper);
+
+ let filters = JSON.parse(row.filters_json || '[]');
+ _show_filters(filters, table);
+
+ table.on('click', () => {
+ frappe.model.with_doctype(row.document_type, function() {
+ let dialog = new frappe.ui.Dialog({
+ title: __('Set Filters'),
+ fields: [
+ {
+ fieldtype: 'HTML',
+ label: 'Filters',
+ fieldname: 'filter_area',
+ }
+ ],
+ primary_action: function() {
+ let values = filter_group.get_filters();
+ let flt = []
+ if (values) {
+ values.forEach(function(value) {
+ flt.push([value[0], value[1], value[2], value[3]]);
+ });
+ }
+ row.filters_json = JSON.stringify(flt);
+ _show_filters(flt, table);
+ dialog.hide();
+ },
+ primary_action_label: "Set"
+ });
+
+ let filter_group = new frappe.ui.FilterGroup({
+ parent: dialog.get_field('filter_area').$wrapper,
+ doctype: row.document_type,
+ on_change: () => {},
+ });
+ filter_group.add_filters_to_filter_group(filters);
+ dialog.show();
+ })
+ });
+ },
+});
\ No newline at end of file
diff --git a/frappe/custom/doctype/package/package.py b/frappe/custom/doctype/package/package.py
index e3b6468791..06edcc4ce0 100644
--- a/frappe/custom/doctype/package/package.py
+++ b/frappe/custom/doctype/package/package.py
@@ -18,14 +18,12 @@ def export_package():
package = []
for doctype in package_doc.export_package:
- filters, or_filters = {}, {}
+ filters = []
- if doctype.get("filters"):
- filters = json.loads(doctype.get("filters"))
- if doctype.get("or_filters"):
- or_filters = json.loads(doctype.get("or_filters"))
+ if doctype.get("filters_json"):
+ filters = json.loads(doctype.get("filters_json"))
- docs = frappe.get_all(doctype.get("document_type"), filters=filters, or_filters=or_filters)
+ docs = frappe.get_all(doctype.get("document_type"), filters=filters)
length = len(docs)
for idx, doc in enumerate(docs):
frappe.publish_realtime("exporting_package", dict(progress=idx, total=length, message=doctype.get("document_type")), user=frappe.session.user)
@@ -36,18 +34,21 @@ def export_package():
})
@frappe.whitelist()
-def import_package():
+def import_package(package=None):
"""Import package from JSON"""
- package_file = frappe.get_all("File", filters={
- "attached_to_doctype": "Package",
- "attached_to_name": "Package"
- }, limit=1, order_by="creation desc")
+ if not package:
+ package_file = frappe.get_all("File", filters={
+ "attached_to_doctype": "Package",
+ "attached_to_name": "Package"
+ }, limit=1, order_by="creation desc")
- if not package_file:
- return
+ if not package_file:
+ return
- content = json.loads(frappe.get_doc("File", package_file[0].name).get_content())
+ package = frappe.get_doc("File", package_file[0].name).get_content()
+
+ content = json.loads(package)
length = len(content)
for idx, doc in enumerate(content):
diff --git a/frappe/custom/doctype/package_doctype/package_doctype.json b/frappe/custom/doctype/package_doctype/package_doctype.json
index cfc4cbbe8f..353f01a673 100644
--- a/frappe/custom/doctype/package_doctype/package_doctype.json
+++ b/frappe/custom/doctype/package_doctype/package_doctype.json
@@ -6,10 +6,8 @@
"engine": "InnoDB",
"field_order": [
"document_type",
- "sb_00",
- "filters",
- "cb_00",
- "or_filters"
+ "section_break_4",
+ "filters_json"
],
"fields": [
{
@@ -21,29 +19,19 @@
"reqd": 1
},
{
- "fieldname": "sb_00",
+ "fieldname": "filters_json",
+ "fieldtype": "Code",
+ "label": "Filters",
+ "options": "JSON"
+ },
+ {
+ "fieldname": "section_break_4",
"fieldtype": "Section Break"
- },
- {
- "fieldname": "filters",
- "fieldtype": "Code",
- "in_list_view": 1,
- "label": "Filters"
- },
- {
- "fieldname": "cb_00",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "or_filters",
- "fieldtype": "Code",
- "in_list_view": 1,
- "label": "Or Filters"
}
],
"istable": 1,
"links": [],
- "modified": "2020-03-14 11:20:42.875446",
+ "modified": "2020-03-16 22:11:40.479498",
"modified_by": "Administrator",
"module": "Custom",
"name": "Package DocType",
From f0ec5cec0e0da7b07caf1172fbb8e20fa8cf2230 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Tue, 17 Mar 2020 11:37:47 +0530
Subject: [PATCH 018/307] feat: package migrator
---
.../doctype/package_migration/__init__.py | 0
.../package_migration/package_migration.js | 51 +++++++++++++++++++
.../package_migration/package_migration.json | 42 +++++++++++++++
.../package_migration/package_migration.py | 28 ++++++++++
.../test_package_migration.py | 10 ++++
5 files changed, 131 insertions(+)
create mode 100644 frappe/custom/doctype/package_migration/__init__.py
create mode 100644 frappe/custom/doctype/package_migration/package_migration.js
create mode 100644 frappe/custom/doctype/package_migration/package_migration.json
create mode 100644 frappe/custom/doctype/package_migration/package_migration.py
create mode 100644 frappe/custom/doctype/package_migration/test_package_migration.py
diff --git a/frappe/custom/doctype/package_migration/__init__.py b/frappe/custom/doctype/package_migration/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frappe/custom/doctype/package_migration/package_migration.js b/frappe/custom/doctype/package_migration/package_migration.js
new file mode 100644
index 0000000000..020092f5f3
--- /dev/null
+++ b/frappe/custom/doctype/package_migration/package_migration.js
@@ -0,0 +1,51 @@
+// Copyright (c) 2020, Frappe Technologies and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Package Migration', {
+ refresh: function(frm) {
+ if (frm.doc.attach) {
+ frm.add_custom_button(__("Connect"), function() {
+ let dialog = new frappe.ui.Dialog({
+ title: __('Connect to Remote Instance'),
+ fields: [
+ {
+ fieldtype: 'Data',
+ label: 'Remote Instance',
+ fieldname: 'remote_instance',
+ reqd: 1
+ },
+ {
+ fieldtype: 'Data',
+ label: 'User',
+ fieldname: 'user',
+ reqd: 1
+ },
+ {
+ fieldtype: 'Password',
+ label: 'Password',
+ fieldname: 'password',
+ reqd: 1
+ },
+ ],
+ primary_action: function() {
+ let values = dialog.get_values();
+ frm.call("install_package_to_remote", {
+ "remote_instance": values.remote_instance,
+ "user": values.user,
+ "password": values.password
+ }).then((r) => {
+ console.log(r);
+ })
+ dialog.hide();
+ },
+ primary_action_label: "Execute"
+ });
+ dialog.show();
+ })
+ }
+ }
+});
+
+// "erpnext_support_password": "uYrMeEhb2NzuEGOk",
+// "erpnext_support_url": "https://marketplace.erpnext.com",
+// "erpnext_support_user": "erpnext_support_fQrhUujW@erpnext.com",
\ No newline at end of file
diff --git a/frappe/custom/doctype/package_migration/package_migration.json b/frappe/custom/doctype/package_migration/package_migration.json
new file mode 100644
index 0000000000..a3c230502b
--- /dev/null
+++ b/frappe/custom/doctype/package_migration/package_migration.json
@@ -0,0 +1,42 @@
+{
+ "actions": [],
+ "creation": "2020-03-17 00:13:31.851579",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "attach"
+ ],
+ "fields": [
+ {
+ "fieldname": "attach",
+ "fieldtype": "Attach",
+ "in_list_view": 1,
+ "label": "Attach",
+ "reqd": 1
+ }
+ ],
+ "issingle": 1,
+ "links": [],
+ "modified": "2020-03-17 10:00:26.676328",
+ "modified_by": "Administrator",
+ "module": "Custom",
+ "name": "Package Migration",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/frappe/custom/doctype/package_migration/package_migration.py b/frappe/custom/doctype/package_migration/package_migration.py
new file mode 100644
index 0000000000..cdcbc0bd19
--- /dev/null
+++ b/frappe/custom/doctype/package_migration/package_migration.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.frappeclient import FrappeClient
+from frappe.model.document import Document
+from frappe import _
+
+class PackageMigration(Document):
+
+ def install_package_to_remote(self, remote_instance, user, password):
+ connection = FrappeClient(remote_instance, user, password)
+
+ package_file = frappe.get_all("File", filters={
+ "attached_to_doctype": "Package Migration",
+ "attached_to_name": "Package Migration"
+ }, limit=1, order_by="creation desc")
+
+ try:
+ connection.post_request({
+ "cmd": "frappe.custom.doctype.package.package.import_package",
+ "package": frappe.get_doc("File", package_file[0].name).get_content()
+ })
+ except Exception:
+ frappe.log_error(frappe.get_traceback())
+ frappe.throw(_("Could not connect to Remote Site."))
diff --git a/frappe/custom/doctype/package_migration/test_package_migration.py b/frappe/custom/doctype/package_migration/test_package_migration.py
new file mode 100644
index 0000000000..8b438145e8
--- /dev/null
+++ b/frappe/custom/doctype/package_migration/test_package_migration.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestPackageMigration(unittest.TestCase):
+ pass
From 230d78df2511032f7bc93021b004ab1786911726 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 18 Mar 2020 16:16:41 +0530
Subject: [PATCH 019/307] feat: deploy remote instance with package
---
frappe/custom/doctype/package/package.js | 42 ++---------
frappe/custom/doctype/package/package.json | 37 +--------
frappe/custom/doctype/package/package.py | 75 ++++++++++++-------
.../package_doctype/package_doctype.json | 23 +++++-
.../package_migration/package_migration.js | 51 -------------
.../package_migration/package_migration.py | 28 -------
.../__init__.py | 0
frappe/custom/doctype/release/release.js | 22 ++++++
.../release.json} | 17 ++---
frappe/custom/doctype/release/release.py | 45 +++++++++++
.../test_release.py} | 2 +-
.../doctype/release_instance/__init__.py | 0
.../release_instance/release_instance.json | 31 ++++++++
.../release_instance/release_instance.py | 10 +++
.../doctype/remote_instance/__init__.py | 0
.../remote_instance/remote_instance.js | 8 ++
.../remote_instance/remote_instance.json | 67 +++++++++++++++++
.../remote_instance/remote_instance.py | 10 +++
.../remote_instance/test_remote_instance.py | 10 +++
19 files changed, 290 insertions(+), 188 deletions(-)
delete mode 100644 frappe/custom/doctype/package_migration/package_migration.js
delete mode 100644 frappe/custom/doctype/package_migration/package_migration.py
rename frappe/custom/doctype/{package_migration => release}/__init__.py (100%)
create mode 100644 frappe/custom/doctype/release/release.js
rename frappe/custom/doctype/{package_migration/package_migration.json => release/release.json} (67%)
create mode 100644 frappe/custom/doctype/release/release.py
rename frappe/custom/doctype/{package_migration/test_package_migration.py => release/test_release.py} (79%)
create mode 100644 frappe/custom/doctype/release_instance/__init__.py
create mode 100644 frappe/custom/doctype/release_instance/release_instance.json
create mode 100644 frappe/custom/doctype/release_instance/release_instance.py
create mode 100644 frappe/custom/doctype/remote_instance/__init__.py
create mode 100644 frappe/custom/doctype/remote_instance/remote_instance.js
create mode 100644 frappe/custom/doctype/remote_instance/remote_instance.json
create mode 100644 frappe/custom/doctype/remote_instance/remote_instance.py
create mode 100644 frappe/custom/doctype/remote_instance/test_remote_instance.py
diff --git a/frappe/custom/doctype/package/package.js b/frappe/custom/doctype/package/package.js
index 08ec8ac96b..2fb0b8eb1d 100644
--- a/frappe/custom/doctype/package/package.js
+++ b/frappe/custom/doctype/package/package.js
@@ -3,44 +3,12 @@
frappe.ui.form.on('Package', {
refresh: function(frm) {
- frappe.realtime.on("exporting_package", (data) => {
- if (data.progress !== (data.total-1)) {
- frm.dashboard.show_progress("Exporting", data.progress / data.total * 100, __("{0}", [data.message]));
- } else {
- frm.dashboard.hide_progress();
- }
- });
-
- frappe.realtime.on("importing_package", (data) => {
- if (data.progress !== (data.total-1)) {
- frm.dashboard.show_progress("Importing", data.progress / data.total * 100, __("{0}", [data.message]));
- } else {
- frm.dashboard.hide_progress();
- }
- });
+ if (frm.doc.export_package) {
+ frm.add_custom_button(__("Go to Release"), function() {
+ frappe.set_route("Form", "Release", "Release");
+ });
+ }
},
- export: function(frm) {
- frappe.call({
- method: 'frappe.custom.doctype.package.package.export_package',
- callback: function(r) {
- if (r.message) {
- const args = {
- cmd: 'frappe.custom.doctype.package.package.download_package',
- data: r.message.data
- };
- open_url_post(frappe.request.url, args, true);
- }
- }
- });
- },
- import: function(frm) {
- frappe.call({
- method: 'frappe.custom.doctype.package.package.import_package',
- callback: function() {
- frappe.msgprint(__("Package Imported."));
- }
- });
- }
});
frappe.ui.form.on('Package DocType', {
diff --git a/frappe/custom/doctype/package/package.json b/frappe/custom/doctype/package/package.json
index cad2ca6788..1d71b744d1 100644
--- a/frappe/custom/doctype/package/package.json
+++ b/frappe/custom/doctype/package/package.json
@@ -5,51 +5,20 @@
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
- "sb_00",
- "export_package",
- "export",
- "sb_01",
- "import_package",
- "import"
+ "export_package"
],
"fields": [
{
- "fieldname": "sb_00",
- "fieldtype": "Section Break",
- "label": "Export Package"
- },
- {
- "depends_on": "export_package",
- "fieldname": "export",
- "fieldtype": "Button",
- "label": "Export"
- },
- {
- "fieldname": "sb_01",
- "fieldtype": "Section Break",
- "label": "Import Package"
- },
- {
- "depends_on": "import_package",
- "fieldname": "import",
- "fieldtype": "Button",
- "label": "Import"
- },
- {
+ "description": "Click on the row for accessing filters.",
"fieldname": "export_package",
"fieldtype": "Table",
"label": "Package",
"options": "Package DocType"
- },
- {
- "fieldname": "import_package",
- "fieldtype": "Attach",
- "label": "Attach"
}
],
"issingle": 1,
"links": [],
- "modified": "2020-03-14 11:52:58.221081",
+ "modified": "2020-03-17 16:41:13.542896",
"modified_by": "Administrator",
"module": "Custom",
"name": "Package",
diff --git a/frappe/custom/doctype/package/package.py b/frappe/custom/doctype/package/package.py
index 06edcc4ce0..a51386acfc 100644
--- a/frappe/custom/doctype/package/package.py
+++ b/frappe/custom/doctype/package/package.py
@@ -4,8 +4,10 @@
from __future__ import unicode_literals
import frappe
-from frappe.model.document import Document
import json
+from frappe.model.document import Document
+from frappe.core.doctype.version.version import get_diff
+from frappe.utils.file_manager import save_file
class Package(Document):
pass
@@ -25,9 +27,29 @@ def export_package():
docs = frappe.get_all(doctype.get("document_type"), filters=filters)
length = len(docs)
+
for idx, doc in enumerate(docs):
- frappe.publish_realtime("exporting_package", dict(progress=idx, total=length, message=doctype.get("document_type")), user=frappe.session.user)
- package.append(frappe.get_doc(doctype.get("document_type"), doc.name).as_dict())
+ frappe.publish_realtime("exporting_package", {"progress":idx, "total":length, "message":doctype.get("document_type")},
+ user=frappe.session.user)
+
+ document = frappe.get_doc(doctype.get("document_type"), doc.name).as_dict()
+
+ if doctype.attachments:
+ attachments = []
+ filters = {"attached_to_doctype": document.get("doctype"), "attached_to_name": document.get("doctype")}
+ for f in frappe.get_list("File", filters=filters):
+ attachments.append({
+ "fname": f.name,
+ "content": frappe.get_doc("File", f.name).get_content()
+ })
+
+ document.update({"attachments": json.dumps(attachments)})
+
+ if doctype.overwrite:
+ document.update({"overwrite": 1})
+
+ document.update({"modified": frappe.utils.get_datetime_str(document.get("modified"))})
+ package.append(document)
return frappe._dict({
"data": post_process(package)
@@ -37,26 +59,33 @@ def export_package():
def import_package(package=None):
"""Import package from JSON"""
- if not package:
- package_file = frappe.get_all("File", filters={
- "attached_to_doctype": "Package",
- "attached_to_name": "Package"
- }, limit=1, order_by="creation desc")
-
- if not package_file:
- return
-
- package = frappe.get_doc("File", package_file[0].name).get_content()
-
content = json.loads(package)
length = len(content)
- for idx, doc in enumerate(content):
- frappe.publish_realtime("importing_package", dict(progress=idx, total=length, message=doc.get("doctype")), user=frappe.session.user)
- frappe.get_doc(doc).insert(ignore_permissions=True, ignore_if_duplicate=True)
+ for doc in content:
+ docname = doc.pop("name")
+ modified = doc.pop("modified")
+ overwrite = doc.pop("overwrite")
+ exists = frappe.db.exists(doc.get("doctype"), docname)
+
+ if not exists:
+ d = frappe.get_doc(doc).insert(ignore_permissions=True, ignore_if_duplicate=True)
+ if doc.get("attachments"):
+ add_attachment(doc.get("attachments"), d)
+ elif exists and overwrite:
+ document = frappe.get_doc(doc.get("doctype"), doc.pop("name"))
+ if frappe.utils.get_datetime(document.modified) < frappe.utils.get_datetime(modified):
+ document.update(doc)
+ document.save()
+ if doc.get("attachments"):
+ add_attachment(doc.get("attachments"), document)
+
+def add_attachment(attachments, doc):
+ for attachment in attachments:
+ save_file(attachment.get("fname"), attachment.get("content"), doc.get("doctype"), doc.get("name"))
def post_process(package):
- del_keys = ('modified_by', 'creation', 'owner', 'idx', 'name', 'modified', 'docstatus')
+ del_keys = ('modified_by', 'creation', 'owner', 'idx', 'docstatus')
for doc in package:
for key in del_keys:
@@ -68,16 +97,8 @@ def post_process(package):
continue
for child in value:
- for key in del_keys:
+ for key in del_keys + ('name'):
if key in child:
del child[key]
return package
-
-@frappe.whitelist()
-def download_package():
- data = frappe._dict(frappe.local.form_dict)
- frappe.response['filename'] = 'Package.json'
- frappe.response['filecontent'] = data.get("data")
- frappe.response['content_type'] = 'application/json'
- frappe.response['type'] = 'download'
diff --git a/frappe/custom/doctype/package_doctype/package_doctype.json b/frappe/custom/doctype/package_doctype/package_doctype.json
index 353f01a673..058cff6480 100644
--- a/frappe/custom/doctype/package_doctype/package_doctype.json
+++ b/frappe/custom/doctype/package_doctype/package_doctype.json
@@ -6,6 +6,9 @@
"engine": "InnoDB",
"field_order": [
"document_type",
+ "column_break_2",
+ "attachments",
+ "overwrite",
"section_break_4",
"filters_json"
],
@@ -27,11 +30,29 @@
{
"fieldname": "section_break_4",
"fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break"
+ },
+ {
+ "default": "0",
+ "fieldname": "attachments",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Include Attachments"
+ },
+ {
+ "default": "0",
+ "fieldname": "overwrite",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Overwrite"
}
],
"istable": 1,
"links": [],
- "modified": "2020-03-16 22:11:40.479498",
+ "modified": "2020-03-17 17:27:58.859896",
"modified_by": "Administrator",
"module": "Custom",
"name": "Package DocType",
diff --git a/frappe/custom/doctype/package_migration/package_migration.js b/frappe/custom/doctype/package_migration/package_migration.js
deleted file mode 100644
index 020092f5f3..0000000000
--- a/frappe/custom/doctype/package_migration/package_migration.js
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2020, Frappe Technologies and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Package Migration', {
- refresh: function(frm) {
- if (frm.doc.attach) {
- frm.add_custom_button(__("Connect"), function() {
- let dialog = new frappe.ui.Dialog({
- title: __('Connect to Remote Instance'),
- fields: [
- {
- fieldtype: 'Data',
- label: 'Remote Instance',
- fieldname: 'remote_instance',
- reqd: 1
- },
- {
- fieldtype: 'Data',
- label: 'User',
- fieldname: 'user',
- reqd: 1
- },
- {
- fieldtype: 'Password',
- label: 'Password',
- fieldname: 'password',
- reqd: 1
- },
- ],
- primary_action: function() {
- let values = dialog.get_values();
- frm.call("install_package_to_remote", {
- "remote_instance": values.remote_instance,
- "user": values.user,
- "password": values.password
- }).then((r) => {
- console.log(r);
- })
- dialog.hide();
- },
- primary_action_label: "Execute"
- });
- dialog.show();
- })
- }
- }
-});
-
-// "erpnext_support_password": "uYrMeEhb2NzuEGOk",
-// "erpnext_support_url": "https://marketplace.erpnext.com",
-// "erpnext_support_user": "erpnext_support_fQrhUujW@erpnext.com",
\ No newline at end of file
diff --git a/frappe/custom/doctype/package_migration/package_migration.py b/frappe/custom/doctype/package_migration/package_migration.py
deleted file mode 100644
index cdcbc0bd19..0000000000
--- a/frappe/custom/doctype/package_migration/package_migration.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2020, Frappe Technologies and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.frappeclient import FrappeClient
-from frappe.model.document import Document
-from frappe import _
-
-class PackageMigration(Document):
-
- def install_package_to_remote(self, remote_instance, user, password):
- connection = FrappeClient(remote_instance, user, password)
-
- package_file = frappe.get_all("File", filters={
- "attached_to_doctype": "Package Migration",
- "attached_to_name": "Package Migration"
- }, limit=1, order_by="creation desc")
-
- try:
- connection.post_request({
- "cmd": "frappe.custom.doctype.package.package.import_package",
- "package": frappe.get_doc("File", package_file[0].name).get_content()
- })
- except Exception:
- frappe.log_error(frappe.get_traceback())
- frappe.throw(_("Could not connect to Remote Site."))
diff --git a/frappe/custom/doctype/package_migration/__init__.py b/frappe/custom/doctype/release/__init__.py
similarity index 100%
rename from frappe/custom/doctype/package_migration/__init__.py
rename to frappe/custom/doctype/release/__init__.py
diff --git a/frappe/custom/doctype/release/release.js b/frappe/custom/doctype/release/release.js
new file mode 100644
index 0000000000..b0919bef43
--- /dev/null
+++ b/frappe/custom/doctype/release/release.js
@@ -0,0 +1,22 @@
+// Copyright (c) 2020, Frappe Technologies and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Release', {
+ refresh: function(frm) {
+ frm.add_custom_button(__("Go to Package"), function() {
+ frappe.set_route("Form", "Package", "Package");
+ });
+
+ frm.add_custom_button(__("Release"), function() {
+ frm.call("create_release").then(() => {});
+ });
+
+ frappe.realtime.on("exporting_package", (data) => {
+ if (data.progress !== (data.total-1)) {
+ frm.dashboard.show_progress("Releasing Package", data.progress / data.total * 100, __("{0}", [data.message]));
+ } else {
+ frm.dashboard.hide_progress();
+ }
+ });
+ }
+});
diff --git a/frappe/custom/doctype/package_migration/package_migration.json b/frappe/custom/doctype/release/release.json
similarity index 67%
rename from frappe/custom/doctype/package_migration/package_migration.json
rename to frappe/custom/doctype/release/release.json
index a3c230502b..ffe7c599cc 100644
--- a/frappe/custom/doctype/package_migration/package_migration.json
+++ b/frappe/custom/doctype/release/release.json
@@ -1,27 +1,26 @@
{
"actions": [],
- "creation": "2020-03-17 00:13:31.851579",
+ "creation": "2020-03-17 13:27:30.158389",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
- "attach"
+ "instances"
],
"fields": [
{
- "fieldname": "attach",
- "fieldtype": "Attach",
- "in_list_view": 1,
- "label": "Attach",
- "reqd": 1
+ "fieldname": "instances",
+ "fieldtype": "Table",
+ "label": "Instances",
+ "options": "Release Instance"
}
],
"issingle": 1,
"links": [],
- "modified": "2020-03-17 10:00:26.676328",
+ "modified": "2020-03-17 15:37:21.813063",
"modified_by": "Administrator",
"module": "Custom",
- "name": "Package Migration",
+ "name": "Release",
"owner": "Administrator",
"permissions": [
{
diff --git a/frappe/custom/doctype/release/release.py b/frappe/custom/doctype/release/release.py
new file mode 100644
index 0000000000..27ecf5c459
--- /dev/null
+++ b/frappe/custom/doctype/release/release.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+import json
+from frappe import _
+from frappe.model.document import Document
+from frappe.custom.doctype.package.package import export_package
+from frappe.frappeclient import FrappeClient
+from frappe.utils.file_manager import save_file
+from frappe.model.naming import make_autoname
+from frappe.utils.password import get_decrypted_password
+
+class Release(Document):
+
+ def create_release(self):
+ package = export_package().get("data")
+
+ for dt_file in frappe.get_list("File", filters={"attached_to_doctype": "Release", "attached_to_name": "Release"}):
+ frappe.delete_doc_if_exists("File", dt_file.name)
+
+ file_name = make_autoname("Package")
+ save_file(file_name, json.dumps(package), "Release", "Release")
+
+ length = len(self.instances)
+ for instance in self.instances:
+ message = _("Releasing to {0}").format(instance.instance)
+ frappe.publish_realtime("exporting_package", {"progress": idx, "total": length, "message": message},
+ user=frappe.session.user)
+ remote = frappe.get_doc("Remote Instance", instance.instance)
+ self.install_package_to_remote(remote.instance, remote.user, get_decrypted_password(remote.doctype, remote.name))
+
+ def install_package_to_remote(self, remote_instance, user, password):
+ connection = FrappeClient(remote_instance, user, password)
+
+ try:
+ connection.post_request({
+ "cmd": "frappe.custom.doctype.package.package.import_package",
+ "package": package
+ })
+ except Exception:
+ frappe.log_error(frappe.get_traceback())
+ frappe.throw(_("Could not connect to Site {0}.").format(remote_instance))
diff --git a/frappe/custom/doctype/package_migration/test_package_migration.py b/frappe/custom/doctype/release/test_release.py
similarity index 79%
rename from frappe/custom/doctype/package_migration/test_package_migration.py
rename to frappe/custom/doctype/release/test_release.py
index 8b438145e8..13e4e26ac0 100644
--- a/frappe/custom/doctype/package_migration/test_package_migration.py
+++ b/frappe/custom/doctype/release/test_release.py
@@ -6,5 +6,5 @@ from __future__ import unicode_literals
# import frappe
import unittest
-class TestPackageMigration(unittest.TestCase):
+class TestRelease(unittest.TestCase):
pass
diff --git a/frappe/custom/doctype/release_instance/__init__.py b/frappe/custom/doctype/release_instance/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frappe/custom/doctype/release_instance/release_instance.json b/frappe/custom/doctype/release_instance/release_instance.json
new file mode 100644
index 0000000000..a91b00666f
--- /dev/null
+++ b/frappe/custom/doctype/release_instance/release_instance.json
@@ -0,0 +1,31 @@
+{
+ "actions": [],
+ "creation": "2020-03-17 12:24:29.615432",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "instance"
+ ],
+ "fields": [
+ {
+ "fieldname": "instance",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Instance",
+ "options": "Remote Instance"
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-03-17 13:35:38.456830",
+ "modified_by": "Administrator",
+ "module": "Custom",
+ "name": "Release Instance",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/frappe/custom/doctype/release_instance/release_instance.py b/frappe/custom/doctype/release_instance/release_instance.py
new file mode 100644
index 0000000000..f5b745a9b4
--- /dev/null
+++ b/frappe/custom/doctype/release_instance/release_instance.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class ReleaseInstance(Document):
+ pass
diff --git a/frappe/custom/doctype/remote_instance/__init__.py b/frappe/custom/doctype/remote_instance/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frappe/custom/doctype/remote_instance/remote_instance.js b/frappe/custom/doctype/remote_instance/remote_instance.js
new file mode 100644
index 0000000000..50096efe4a
--- /dev/null
+++ b/frappe/custom/doctype/remote_instance/remote_instance.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, Frappe Technologies and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Remote Instance', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/frappe/custom/doctype/remote_instance/remote_instance.json b/frappe/custom/doctype/remote_instance/remote_instance.json
new file mode 100644
index 0000000000..4224d40c4c
--- /dev/null
+++ b/frappe/custom/doctype/remote_instance/remote_instance.json
@@ -0,0 +1,67 @@
+{
+ "actions": [],
+ "autoname": "field:instance",
+ "creation": "2020-03-17 12:08:33.304631",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "instance",
+ "user",
+ "password"
+ ],
+ "fields": [
+ {
+ "fieldname": "instance",
+ "fieldtype": "Data",
+ "label": "Instance",
+ "unique": 1
+ },
+ {
+ "fieldname": "user",
+ "fieldtype": "Data",
+ "label": "User"
+ },
+ {
+ "fieldname": "password",
+ "fieldtype": "Password",
+ "label": "Password"
+ }
+ ],
+ "links": [],
+ "modified": "2020-03-17 13:34:40.924501",
+ "modified_by": "Administrator",
+ "module": "Custom",
+ "name": "Remote Instance",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "All",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/frappe/custom/doctype/remote_instance/remote_instance.py b/frappe/custom/doctype/remote_instance/remote_instance.py
new file mode 100644
index 0000000000..5fd513a2f6
--- /dev/null
+++ b/frappe/custom/doctype/remote_instance/remote_instance.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class RemoteInstance(Document):
+ pass
diff --git a/frappe/custom/doctype/remote_instance/test_remote_instance.py b/frappe/custom/doctype/remote_instance/test_remote_instance.py
new file mode 100644
index 0000000000..0eb7561bf5
--- /dev/null
+++ b/frappe/custom/doctype/remote_instance/test_remote_instance.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestRemoteInstance(unittest.TestCase):
+ pass
From a02847f12676f310b637ad1cfb89436c24896613 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 18 Mar 2020 23:18:06 +0530
Subject: [PATCH 020/307] fix: remove release instance doctype
---
frappe/custom/doctype/package/package.py | 17 +++--
frappe/custom/doctype/release/release.js | 9 +--
frappe/custom/doctype/release/release.json | 4 +-
frappe/custom/doctype/release/release.py | 25 +++----
.../release_instance.js} | 2 +-
.../release_instance/release_instance.json | 57 ++++++++++++++--
.../test_release_instance.py} | 2 +-
.../__init__.py | 0
.../release_instance_list.json | 32 +++++++++
.../release_instance_list.py} | 2 +-
.../remote_instance/remote_instance.json | 67 -------------------
11 files changed, 116 insertions(+), 101 deletions(-)
rename frappe/custom/doctype/{remote_instance/remote_instance.js => release_instance/release_instance.js} (79%)
rename frappe/custom/doctype/{remote_instance/test_remote_instance.py => release_instance/test_release_instance.py} (79%)
rename frappe/custom/doctype/{remote_instance => release_instance_list}/__init__.py (100%)
create mode 100644 frappe/custom/doctype/release_instance_list/release_instance_list.json
rename frappe/custom/doctype/{remote_instance/remote_instance.py => release_instance_list/release_instance_list.py} (86%)
delete mode 100644 frappe/custom/doctype/remote_instance/remote_instance.json
diff --git a/frappe/custom/doctype/package/package.py b/frappe/custom/doctype/package/package.py
index a51386acfc..bedc567066 100644
--- a/frappe/custom/doctype/package/package.py
+++ b/frappe/custom/doctype/package/package.py
@@ -5,9 +5,11 @@
from __future__ import unicode_literals
import frappe
import json
+import pickle
from frappe.model.document import Document
from frappe.core.doctype.version.version import get_diff
from frappe.utils.file_manager import save_file
+from frappe import _
class Package(Document):
pass
@@ -29,7 +31,7 @@ def export_package():
length = len(docs)
for idx, doc in enumerate(docs):
- frappe.publish_realtime("exporting_package", {"progress":idx, "total":length, "message":doctype.get("document_type")},
+ frappe.publish_realtime("package", {"progress":idx, "total":length, "message":doctype.get("document_type"), "prefix": _("Exporting")},
user=frappe.session.user)
document = frappe.get_doc(doctype.get("document_type"), doc.name).as_dict()
@@ -51,15 +53,13 @@ def export_package():
document.update({"modified": frappe.utils.get_datetime_str(document.get("modified"))})
package.append(document)
- return frappe._dict({
- "data": post_process(package)
- })
+ return post_process(package)
@frappe.whitelist()
def import_package(package=None):
"""Import package from JSON"""
- content = json.loads(package)
+ content = pickle.loads(package)
length = len(content)
for doc in content:
@@ -85,7 +85,12 @@ def add_attachment(attachments, doc):
save_file(attachment.get("fname"), attachment.get("content"), doc.get("doctype"), doc.get("name"))
def post_process(package):
+ """
+ Remove the keys from Document and Child Document
+ Convert datetime, date, time to str
+ """
del_keys = ('modified_by', 'creation', 'owner', 'idx', 'docstatus')
+ child_del_keys = ('modified_by', 'creation', 'owner', 'idx', 'docstatus', 'name')
for doc in package:
for key in del_keys:
@@ -97,7 +102,7 @@ def post_process(package):
continue
for child in value:
- for key in del_keys + ('name'):
+ for key in child_del_keys:
if key in child:
del child[key]
diff --git a/frappe/custom/doctype/release/release.js b/frappe/custom/doctype/release/release.js
index b0919bef43..709ae18d36 100644
--- a/frappe/custom/doctype/release/release.js
+++ b/frappe/custom/doctype/release/release.js
@@ -8,12 +8,13 @@ frappe.ui.form.on('Release', {
});
frm.add_custom_button(__("Release"), function() {
- frm.call("create_release").then(() => {});
+ frm.call("create_release");
});
- frappe.realtime.on("exporting_package", (data) => {
- if (data.progress !== (data.total-1)) {
- frm.dashboard.show_progress("Releasing Package", data.progress / data.total * 100, __("{0}", [data.message]));
+ frappe.realtime.on("package", (data) => {
+ frm.dashboard.show_progress(data.prefix, data.progress / data.total * 100, __("{0}", [data.message]));
+ if ((data.progress+1) != data.total) {
+ frm.dashboard.show_progress(data.prefix, data.progress / data.total * 100, __("{0}", [data.message]));
} else {
frm.dashboard.hide_progress();
}
diff --git a/frappe/custom/doctype/release/release.json b/frappe/custom/doctype/release/release.json
index ffe7c599cc..ba6c69c49f 100644
--- a/frappe/custom/doctype/release/release.json
+++ b/frappe/custom/doctype/release/release.json
@@ -12,12 +12,12 @@
"fieldname": "instances",
"fieldtype": "Table",
"label": "Instances",
- "options": "Release Instance"
+ "options": "Release Instance List"
}
],
"issingle": 1,
"links": [],
- "modified": "2020-03-17 15:37:21.813063",
+ "modified": "2020-03-18 18:25:23.539372",
"modified_by": "Administrator",
"module": "Custom",
"name": "Release",
diff --git a/frappe/custom/doctype/release/release.py b/frappe/custom/doctype/release/release.py
index 27ecf5c459..ae798f7d85 100644
--- a/frappe/custom/doctype/release/release.py
+++ b/frappe/custom/doctype/release/release.py
@@ -5,6 +5,7 @@
from __future__ import unicode_literals
import frappe
import json
+import pickle
from frappe import _
from frappe.model.document import Document
from frappe.custom.doctype.package.package import export_package
@@ -16,30 +17,30 @@ from frappe.utils.password import get_decrypted_password
class Release(Document):
def create_release(self):
- package = export_package().get("data")
+ package = export_package()
for dt_file in frappe.get_list("File", filters={"attached_to_doctype": "Release", "attached_to_name": "Release"}):
frappe.delete_doc_if_exists("File", dt_file.name)
file_name = make_autoname("Package")
- save_file(file_name, json.dumps(package), "Release", "Release")
+ save_file(file_name, pickle.dumps(package), "Release", "Release")
length = len(self.instances)
- for instance in self.instances:
- message = _("Releasing to {0}").format(instance.instance)
- frappe.publish_realtime("exporting_package", {"progress": idx, "total": length, "message": message},
+ for idx, instance in enumerate(self.instances):
+ frappe.publish_realtime("package", {"progress": idx, "total": length, "message": instance.instance, "prefix": _("Deploying")},
user=frappe.session.user)
- remote = frappe.get_doc("Remote Instance", instance.instance)
- self.install_package_to_remote(remote.instance, remote.user, get_decrypted_password(remote.doctype, remote.name))
- def install_package_to_remote(self, remote_instance, user, password):
- connection = FrappeClient(remote_instance, user, password)
+ self.install_package_to_remote(package, instance)
+
+ def install_package_to_remote(self, package, instance):
+ remote = frappe.get_doc("Release Instance", instance.instance)
+ connection = FrappeClient(remote.instance, remote.user, get_decrypted_password(remote.doctype, remote.name))
try:
connection.post_request({
"cmd": "frappe.custom.doctype.package.package.import_package",
- "package": package
+ "package": pickle.dumps(package)
})
- except Exception:
+ except Exception as e:
frappe.log_error(frappe.get_traceback())
- frappe.throw(_("Could not connect to Site {0}.").format(remote_instance))
+ frappe.throw(_("Error while installing package to site {0}. Please check Error Logs.").format(remote.instance))
diff --git a/frappe/custom/doctype/remote_instance/remote_instance.js b/frappe/custom/doctype/release_instance/release_instance.js
similarity index 79%
rename from frappe/custom/doctype/remote_instance/remote_instance.js
rename to frappe/custom/doctype/release_instance/release_instance.js
index 50096efe4a..7447c9c706 100644
--- a/frappe/custom/doctype/remote_instance/remote_instance.js
+++ b/frappe/custom/doctype/release_instance/release_instance.js
@@ -1,7 +1,7 @@
// Copyright (c) 2020, Frappe Technologies and contributors
// For license information, please see license.txt
-frappe.ui.form.on('Remote Instance', {
+frappe.ui.form.on('Release Instance', {
// refresh: function(frm) {
// }
diff --git a/frappe/custom/doctype/release_instance/release_instance.json b/frappe/custom/doctype/release_instance/release_instance.json
index a91b00666f..d1bf07db59 100644
--- a/frappe/custom/doctype/release_instance/release_instance.json
+++ b/frappe/custom/doctype/release_instance/release_instance.json
@@ -1,29 +1,72 @@
{
"actions": [],
+ "autoname": "field:instance",
"creation": "2020-03-17 12:24:29.615432",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
- "instance"
+ "instance",
+ "user",
+ "password"
],
"fields": [
{
"fieldname": "instance",
- "fieldtype": "Link",
+ "fieldtype": "Data",
"in_list_view": 1,
- "label": "Instance",
- "options": "Remote Instance"
+ "in_standard_filter": 1,
+ "label": "Instance URL",
+ "unique": 1
+ },
+ {
+ "fieldname": "user",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "User",
+ "options": "Email"
+ },
+ {
+ "fieldname": "password",
+ "fieldtype": "Password",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Password"
}
],
- "istable": 1,
"links": [],
- "modified": "2020-03-17 13:35:38.456830",
+ "modified": "2020-03-18 18:54:55.801749",
"modified_by": "Administrator",
"module": "Custom",
"name": "Release Instance",
"owner": "Administrator",
- "permissions": [],
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "All",
+ "share": 1,
+ "write": 1
+ }
+ ],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
diff --git a/frappe/custom/doctype/remote_instance/test_remote_instance.py b/frappe/custom/doctype/release_instance/test_release_instance.py
similarity index 79%
rename from frappe/custom/doctype/remote_instance/test_remote_instance.py
rename to frappe/custom/doctype/release_instance/test_release_instance.py
index 0eb7561bf5..95df304262 100644
--- a/frappe/custom/doctype/remote_instance/test_remote_instance.py
+++ b/frappe/custom/doctype/release_instance/test_release_instance.py
@@ -6,5 +6,5 @@ from __future__ import unicode_literals
# import frappe
import unittest
-class TestRemoteInstance(unittest.TestCase):
+class TestReleaseInstance(unittest.TestCase):
pass
diff --git a/frappe/custom/doctype/remote_instance/__init__.py b/frappe/custom/doctype/release_instance_list/__init__.py
similarity index 100%
rename from frappe/custom/doctype/remote_instance/__init__.py
rename to frappe/custom/doctype/release_instance_list/__init__.py
diff --git a/frappe/custom/doctype/release_instance_list/release_instance_list.json b/frappe/custom/doctype/release_instance_list/release_instance_list.json
new file mode 100644
index 0000000000..d9b9b63340
--- /dev/null
+++ b/frappe/custom/doctype/release_instance_list/release_instance_list.json
@@ -0,0 +1,32 @@
+{
+ "actions": [],
+ "creation": "2020-03-18 18:25:02.024237",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "instance"
+ ],
+ "fields": [
+ {
+ "fieldname": "instance",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Instance",
+ "options": "Release Instance",
+ "reqd": 1
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-03-18 22:55:20.130597",
+ "modified_by": "Administrator",
+ "module": "Custom",
+ "name": "Release Instance List",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/frappe/custom/doctype/remote_instance/remote_instance.py b/frappe/custom/doctype/release_instance_list/release_instance_list.py
similarity index 86%
rename from frappe/custom/doctype/remote_instance/remote_instance.py
rename to frappe/custom/doctype/release_instance_list/release_instance_list.py
index 5fd513a2f6..f6eb68a535 100644
--- a/frappe/custom/doctype/remote_instance/remote_instance.py
+++ b/frappe/custom/doctype/release_instance_list/release_instance_list.py
@@ -6,5 +6,5 @@ from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
-class RemoteInstance(Document):
+class ReleaseInstanceList(Document):
pass
diff --git a/frappe/custom/doctype/remote_instance/remote_instance.json b/frappe/custom/doctype/remote_instance/remote_instance.json
deleted file mode 100644
index 4224d40c4c..0000000000
--- a/frappe/custom/doctype/remote_instance/remote_instance.json
+++ /dev/null
@@ -1,67 +0,0 @@
-{
- "actions": [],
- "autoname": "field:instance",
- "creation": "2020-03-17 12:08:33.304631",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "instance",
- "user",
- "password"
- ],
- "fields": [
- {
- "fieldname": "instance",
- "fieldtype": "Data",
- "label": "Instance",
- "unique": 1
- },
- {
- "fieldname": "user",
- "fieldtype": "Data",
- "label": "User"
- },
- {
- "fieldname": "password",
- "fieldtype": "Password",
- "label": "Password"
- }
- ],
- "links": [],
- "modified": "2020-03-17 13:34:40.924501",
- "modified_by": "Administrator",
- "module": "Custom",
- "name": "Remote Instance",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "share": 1,
- "write": 1
- },
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "All",
- "share": 1,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
From 1901650514037d29786e2d1841681a39fd7f4648 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Thu, 19 Mar 2020 11:33:25 +0530
Subject: [PATCH 021/307] fix: add utils for converting to string
---
frappe/custom/doctype/package/package.py | 31 ++++++++++++++++++++----
frappe/utils/data.py | 13 ++++++++++
2 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/frappe/custom/doctype/package/package.py b/frappe/custom/doctype/package/package.py
index bedc567066..5ee781c608 100644
--- a/frappe/custom/doctype/package/package.py
+++ b/frappe/custom/doctype/package/package.py
@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
import json
-import pickle
+import datetime
from frappe.model.document import Document
from frappe.core.doctype.version.version import get_diff
from frappe.utils.file_manager import save_file
@@ -59,7 +59,7 @@ def export_package():
def import_package(package=None):
"""Import package from JSON"""
- content = pickle.loads(package)
+ content = json.loads(package)
length = len(content)
for doc in content:
@@ -98,12 +98,33 @@ def post_process(package):
del doc[key]
for key, value in doc.items():
+ stringified_value = get_stringified_value(value)
+ if stringified_value:
+ doc[key] = stringified_value
+
if not isinstance(value, list):
continue
for child in value:
- for key in child_del_keys:
- if key in child:
- del child[key]
+ for child_key in child_del_keys:
+ if child_key in child:
+ del child[child_key]
+
+ for child_key, child_value in child.items():
+ stringified_value = get_stringified_value(child_value)
+ if stringified_value:
+ child[child_key] = stringified_value
return package
+
+def get_stringified_value(value):
+ if isinstance(value, datetime.datetime):
+ return frappe.utils.get_datetime_str(value)
+
+ if isinstance(value, datetime.date):
+ return frappe.utils.get_date_str(value)
+
+ if isinstance(value, datetime.timedelta):
+ return frappe.utils.get_time_str(value)
+
+ return None
\ No newline at end of file
diff --git a/frappe/utils/data.py b/frappe/utils/data.py
index acebfa2271..4c64624098 100644
--- a/frappe/utils/data.py
+++ b/frappe/utils/data.py
@@ -209,6 +209,19 @@ def get_datetime_str(datetime_obj):
datetime_obj = get_datetime(datetime_obj)
return datetime_obj.strftime(DATETIME_FORMAT)
+def get_date_str(date_obj):
+ if isinstance(date_obj, string_types):
+ date_obj = get_datetime(date_obj)
+ return date_obj.strftime(DATE_FORMAT)
+
+def get_time_str(timedelta_obj):
+ if isinstance(timedelta_obj, string_types):
+ timedelta_obj = to_timedelta(date_obj)
+
+ hours, remainder = divmod(timedelta_obj.seconds, 3600)
+ minutes, seconds = divmod(remainder, 60)
+ return "{0}:{1}:{2}".format(hours, minutes, seconds)
+
def get_user_date_format():
"""Get the current user date format. The result will be cached."""
if getattr(frappe.local, "user_date_format", None) is None:
From a47efa8d96c98ba8202755bdf80cdc9292a7f493 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Thu, 19 Mar 2020 18:09:10 +0530
Subject: [PATCH 022/307] fix: file attachments
---
frappe/custom/doctype/package/package.py | 35 ++++++++++++------------
frappe/custom/doctype/release/release.py | 5 ++--
2 files changed, 19 insertions(+), 21 deletions(-)
diff --git a/frappe/custom/doctype/package/package.py b/frappe/custom/doctype/package/package.py
index 5ee781c608..88549b644e 100644
--- a/frappe/custom/doctype/package/package.py
+++ b/frappe/custom/doctype/package/package.py
@@ -6,9 +6,10 @@ from __future__ import unicode_literals
import frappe
import json
import datetime
+import base64
from frappe.model.document import Document
from frappe.core.doctype.version.version import get_diff
-from frappe.utils.file_manager import save_file
+from frappe.utils.file_manager import save_file, get_file
from frappe import _
class Package(Document):
@@ -35,22 +36,19 @@ def export_package():
user=frappe.session.user)
document = frappe.get_doc(doctype.get("document_type"), doc.name).as_dict()
+ attachments = []
if doctype.attachments:
- attachments = []
- filters = {"attached_to_doctype": document.get("doctype"), "attached_to_name": document.get("doctype")}
+ filters = {"attached_to_doctype": document.get("doctype"), "attached_to_name": document.get("name")}
for f in frappe.get_list("File", filters=filters):
- attachments.append({
- "fname": f.name,
- "content": frappe.get_doc("File", f.name).get_content()
- })
+ fname, fcontents = get_file(f.name)
+ attachments.append({"fname": fname, "content": base64.b64encode(fcontents).decode('ascii')})
- document.update({"attachments": json.dumps(attachments)})
+ document.update({
+ "attachments": attachments,
+ "overwrite": True if doctype.overwrite else False
+ })
- if doctype.overwrite:
- document.update({"overwrite": 1})
-
- document.update({"modified": frappe.utils.get_datetime_str(document.get("modified"))})
package.append(document)
return post_process(package)
@@ -66,23 +64,24 @@ def import_package(package=None):
docname = doc.pop("name")
modified = doc.pop("modified")
overwrite = doc.pop("overwrite")
+ attachments = doc.get("attachments")
exists = frappe.db.exists(doc.get("doctype"), docname)
if not exists:
d = frappe.get_doc(doc).insert(ignore_permissions=True, ignore_if_duplicate=True)
- if doc.get("attachments"):
- add_attachment(doc.get("attachments"), d)
+ if attachments:
+ add_attachment(attachments, d)
elif exists and overwrite:
- document = frappe.get_doc(doc.get("doctype"), doc.pop("name"))
+ document = frappe.get_doc(doc.get("doctype"), docname)
if frappe.utils.get_datetime(document.modified) < frappe.utils.get_datetime(modified):
document.update(doc)
document.save()
- if doc.get("attachments"):
- add_attachment(doc.get("attachments"), document)
+ if attachments:
+ add_attachment(attachments, document)
def add_attachment(attachments, doc):
for attachment in attachments:
- save_file(attachment.get("fname"), attachment.get("content"), doc.get("doctype"), doc.get("name"))
+ save_file(attachment.get("fname"), base64.b64decode(attachment.get("content")), doc.get("doctype"), doc.get("name"))
def post_process(package):
"""
diff --git a/frappe/custom/doctype/release/release.py b/frappe/custom/doctype/release/release.py
index ae798f7d85..099e98a4fb 100644
--- a/frappe/custom/doctype/release/release.py
+++ b/frappe/custom/doctype/release/release.py
@@ -5,7 +5,6 @@
from __future__ import unicode_literals
import frappe
import json
-import pickle
from frappe import _
from frappe.model.document import Document
from frappe.custom.doctype.package.package import export_package
@@ -23,7 +22,7 @@ class Release(Document):
frappe.delete_doc_if_exists("File", dt_file.name)
file_name = make_autoname("Package")
- save_file(file_name, pickle.dumps(package), "Release", "Release")
+ save_file(file_name, json.dumps(package), "Release", "Release")
length = len(self.instances)
for idx, instance in enumerate(self.instances):
@@ -39,7 +38,7 @@ class Release(Document):
try:
connection.post_request({
"cmd": "frappe.custom.doctype.package.package.import_package",
- "package": pickle.dumps(package)
+ "package": json.dumps(package)
})
except Exception as e:
frappe.log_error(frappe.get_traceback())
From 4a38cf09838db5c7f64b5f8e1a8e55e509954e52 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Thu, 19 Mar 2020 19:45:21 +0530
Subject: [PATCH 023/307] fix: package import fixes
---
frappe/custom/doctype/package/package.py | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/frappe/custom/doctype/package/package.py b/frappe/custom/doctype/package/package.py
index 88549b644e..31f681486f 100644
--- a/frappe/custom/doctype/package/package.py
+++ b/frappe/custom/doctype/package/package.py
@@ -61,19 +61,19 @@ def import_package(package=None):
length = len(content)
for doc in content:
- docname = doc.pop("name")
modified = doc.pop("modified")
overwrite = doc.pop("overwrite")
- attachments = doc.get("attachments")
- exists = frappe.db.exists(doc.get("doctype"), docname)
+ attachments = doc.pop("attachments")
+ exists = frappe.db.exists(doc.get("doctype"), doc.get("name"))
if not exists:
d = frappe.get_doc(doc).insert(ignore_permissions=True, ignore_if_duplicate=True)
if attachments:
add_attachment(attachments, d)
- elif exists and overwrite:
+ elif exists:
+ docname = doc.pop("name")
document = frappe.get_doc(doc.get("doctype"), docname)
- if frappe.utils.get_datetime(document.modified) < frappe.utils.get_datetime(modified):
+ if frappe.utils.get_datetime(document.modified) < frappe.utils.get_datetime(modified) and not overwrite:
document.update(doc)
document.save()
if attachments:
From b77d93d22af1425fe7ea2a43d08d1a2fb7369f67 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Thu, 19 Mar 2020 21:32:34 +0530
Subject: [PATCH 024/307] fix: add filters for document type in package
---
frappe/custom/doctype/package/package.js | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/frappe/custom/doctype/package/package.js b/frappe/custom/doctype/package/package.js
index 2fb0b8eb1d..f6b908bcf1 100644
--- a/frappe/custom/doctype/package/package.js
+++ b/frappe/custom/doctype/package/package.js
@@ -8,6 +8,14 @@ frappe.ui.form.on('Package', {
frappe.set_route("Form", "Release", "Release");
});
}
+
+ frm.set_query("document_type", "export_package", function () {
+ return {
+ filters: {
+ "istable": 0,
+ }
+ };
+ })
},
});
@@ -54,6 +62,11 @@ frappe.ui.form.on('Package DocType', {
_show_filters(filters, table);
table.on('click', () => {
+ if (!row.document_type) {
+ frappe.msgprint(__("Select Document Type."));
+ return;
+ }
+
frappe.model.with_doctype(row.document_type, function() {
let dialog = new frappe.ui.Dialog({
title: __('Set Filters'),
From 0f1eaee1be856a4df4f2734a9d584cf1e701eebd Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Fri, 20 Mar 2020 13:28:35 +0530
Subject: [PATCH 025/307] feat: add manual import
---
frappe/custom/doctype/package/package.js | 3 +++
frappe/custom/doctype/package/package.json | 24 ++++++++++++++++++++--
frappe/custom/doctype/package/package.py | 21 +++++++++++++++----
frappe/utils/data.py | 2 +-
4 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/frappe/custom/doctype/package/package.js b/frappe/custom/doctype/package/package.js
index f6b908bcf1..aa6fdbe635 100644
--- a/frappe/custom/doctype/package/package.js
+++ b/frappe/custom/doctype/package/package.js
@@ -17,6 +17,9 @@ frappe.ui.form.on('Package', {
};
})
},
+ import: function(frm) {
+ frm.call("import_from_package");
+ }
});
frappe.ui.form.on('Package DocType', {
diff --git a/frappe/custom/doctype/package/package.json b/frappe/custom/doctype/package/package.json
index 1d71b744d1..7bfdf719cf 100644
--- a/frappe/custom/doctype/package/package.json
+++ b/frappe/custom/doctype/package/package.json
@@ -5,7 +5,10 @@
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
- "export_package"
+ "export_package",
+ "import_section",
+ "attach",
+ "import"
],
"fields": [
{
@@ -14,11 +17,28 @@
"fieldtype": "Table",
"label": "Package",
"options": "Package DocType"
+ },
+ {
+ "collapsible": 1,
+ "collapsible_depends_on": "attach",
+ "fieldname": "import_section",
+ "fieldtype": "Section Break",
+ "label": "Import Package"
+ },
+ {
+ "fieldname": "import",
+ "fieldtype": "Button",
+ "label": "Import"
+ },
+ {
+ "fieldname": "attach",
+ "fieldtype": "Attach",
+ "label": "Attach Package"
}
],
"issingle": 1,
"links": [],
- "modified": "2020-03-17 16:41:13.542896",
+ "modified": "2020-03-19 22:03:06.012473",
"modified_by": "Administrator",
"module": "Custom",
"name": "Package",
diff --git a/frappe/custom/doctype/package/package.py b/frappe/custom/doctype/package/package.py
index 31f681486f..2bf5a5f7cc 100644
--- a/frappe/custom/doctype/package/package.py
+++ b/frappe/custom/doctype/package/package.py
@@ -11,9 +11,22 @@ from frappe.model.document import Document
from frappe.core.doctype.version.version import get_diff
from frappe.utils.file_manager import save_file, get_file
from frappe import _
+from six import string_types
class Package(Document):
- pass
+
+ def import_from_package(self):
+ filters = {"attached_to_doctype": "Package", "attached_to_name": "Package"}
+ files = frappe.get_list("File", filters=filters, limit=1, order_by="creation desc")
+ if not files:
+ frappe.msgprint(_("No file attach for Importing."))
+ return
+
+ for f in files:
+ fname, fcontents = get_file(f.name)
+ import_package(fcontents)
+
+ frappe.msgprint(_("Package Imported."))
@frappe.whitelist()
def export_package():
@@ -57,10 +70,10 @@ def export_package():
def import_package(package=None):
"""Import package from JSON"""
- content = json.loads(package)
- length = len(content)
+ if isinstance(package, string_types):
+ package = json.loads(package)
- for doc in content:
+ for doc in package:
modified = doc.pop("modified")
overwrite = doc.pop("overwrite")
attachments = doc.pop("attachments")
diff --git a/frappe/utils/data.py b/frappe/utils/data.py
index 4c64624098..96bdb20841 100644
--- a/frappe/utils/data.py
+++ b/frappe/utils/data.py
@@ -216,7 +216,7 @@ def get_date_str(date_obj):
def get_time_str(timedelta_obj):
if isinstance(timedelta_obj, string_types):
- timedelta_obj = to_timedelta(date_obj)
+ timedelta_obj = to_timedelta(timedelta_obj)
hours, remainder = divmod(timedelta_obj.seconds, 3600)
minutes, seconds = divmod(remainder, 60)
From 8302f251762ea9362ca7b1d1b92f91542b781139 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Fri, 20 Mar 2020 15:21:21 +0530
Subject: [PATCH 026/307] chore: codacy fixes
---
frappe/custom/doctype/package/package.js | 4 ++--
frappe/custom/doctype/package/package.py | 11 ++++-------
frappe/custom/doctype/release/release.py | 9 +++++++--
3 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/frappe/custom/doctype/package/package.js b/frappe/custom/doctype/package/package.js
index aa6fdbe635..a053b7d864 100644
--- a/frappe/custom/doctype/package/package.js
+++ b/frappe/custom/doctype/package/package.js
@@ -82,7 +82,7 @@ frappe.ui.form.on('Package DocType', {
],
primary_action: function() {
let values = filter_group.get_filters();
- let flt = []
+ let flt = [];
if (values) {
values.forEach(function(value) {
flt.push([value[0], value[1], value[2], value[3]]);
@@ -102,7 +102,7 @@ frappe.ui.form.on('Package DocType', {
});
filter_group.add_filters_to_filter_group(filters);
dialog.show();
- })
+ });
});
},
});
\ No newline at end of file
diff --git a/frappe/custom/doctype/package/package.py b/frappe/custom/doctype/package/package.py
index 2bf5a5f7cc..d5da360089 100644
--- a/frappe/custom/doctype/package/package.py
+++ b/frappe/custom/doctype/package/package.py
@@ -8,7 +8,6 @@ import json
import datetime
import base64
from frappe.model.document import Document
-from frappe.core.doctype.version.version import get_diff
from frappe.utils.file_manager import save_file, get_file
from frappe import _
from six import string_types
@@ -30,7 +29,7 @@ class Package(Document):
@frappe.whitelist()
def export_package():
- """Export package as JSON"""
+ """Export package as JSON."""
package_doc = frappe.get_single("Package")
package = []
@@ -68,7 +67,7 @@ def export_package():
@frappe.whitelist()
def import_package(package=None):
- """Import package from JSON"""
+ """Import package from JSON."""
if isinstance(package, string_types):
package = json.loads(package)
@@ -97,10 +96,8 @@ def add_attachment(attachments, doc):
save_file(attachment.get("fname"), base64.b64decode(attachment.get("content")), doc.get("doctype"), doc.get("name"))
def post_process(package):
- """
- Remove the keys from Document and Child Document
- Convert datetime, date, time to str
- """
+ """Remove the keys from Document and Child Document. Convert datetime, date, time to str."""
+
del_keys = ('modified_by', 'creation', 'owner', 'idx', 'docstatus')
child_del_keys = ('modified_by', 'creation', 'owner', 'idx', 'docstatus', 'name')
diff --git a/frappe/custom/doctype/release/release.py b/frappe/custom/doctype/release/release.py
index 099e98a4fb..e68be15778 100644
--- a/frappe/custom/doctype/release/release.py
+++ b/frappe/custom/doctype/release/release.py
@@ -33,13 +33,18 @@ class Release(Document):
def install_package_to_remote(self, package, instance):
remote = frappe.get_doc("Release Instance", instance.instance)
- connection = FrappeClient(remote.instance, remote.user, get_decrypted_password(remote.doctype, remote.name))
+
+ try:
+ connection = FrappeClient(remote.instance, remote.user, get_decrypted_password(remote.doctype, remote.name))
+ except Exception:
+ frappe.log_error(frappe.get_traceback())
+ frappe.throw(_("Couldn't connect to site {0}. Please check Error Logs.").format(remote.instance))
try:
connection.post_request({
"cmd": "frappe.custom.doctype.package.package.import_package",
"package": json.dumps(package)
})
- except Exception as e:
+ except Exception:
frappe.log_error(frappe.get_traceback())
frappe.throw(_("Error while installing package to site {0}. Please check Error Logs.").format(remote.instance))
From ddb02bd7366ec83abe6abd9297b383595cde97da Mon Sep 17 00:00:00 2001
From: Himanshu
Date: Tue, 31 Mar 2020 11:15:01 +0530
Subject: [PATCH 027/307] Update package.js
---
frappe/custom/doctype/package/package.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/frappe/custom/doctype/package/package.js b/frappe/custom/doctype/package/package.js
index a053b7d864..54af424e4d 100644
--- a/frappe/custom/doctype/package/package.js
+++ b/frappe/custom/doctype/package/package.js
@@ -15,7 +15,7 @@ frappe.ui.form.on('Package', {
"istable": 0,
}
};
- })
+ });
},
import: function(frm) {
frm.call("import_from_package");
@@ -105,4 +105,4 @@ frappe.ui.form.on('Package DocType', {
});
});
},
-});
\ No newline at end of file
+});
From c12cfffc84c1800807acebd4380fbd1f72dfc750 Mon Sep 17 00:00:00 2001
From: Himanshu
Date: Tue, 31 Mar 2020 11:45:59 +0530
Subject: [PATCH 028/307] Update package.py
---
frappe/custom/doctype/package/package.py | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/frappe/custom/doctype/package/package.py b/frappe/custom/doctype/package/package.py
index d5da360089..a42de94896 100644
--- a/frappe/custom/doctype/package/package.py
+++ b/frappe/custom/doctype/package/package.py
@@ -30,7 +30,6 @@ class Package(Document):
@frappe.whitelist()
def export_package():
"""Export package as JSON."""
-
package_doc = frappe.get_single("Package")
package = []
@@ -68,7 +67,6 @@ def export_package():
@frappe.whitelist()
def import_package(package=None):
"""Import package from JSON."""
-
if isinstance(package, string_types):
package = json.loads(package)
@@ -97,7 +95,6 @@ def add_attachment(attachments, doc):
def post_process(package):
"""Remove the keys from Document and Child Document. Convert datetime, date, time to str."""
-
del_keys = ('modified_by', 'creation', 'owner', 'idx', 'docstatus')
child_del_keys = ('modified_by', 'creation', 'owner', 'idx', 'docstatus', 'name')
@@ -136,4 +133,4 @@ def get_stringified_value(value):
if isinstance(value, datetime.timedelta):
return frappe.utils.get_time_str(value)
- return None
\ No newline at end of file
+ return None
From 20d54e4588c74920bcbe8033ed2f9a9641f7e0e6 Mon Sep 17 00:00:00 2001
From: Saurabh
Date: Mon, 6 Apr 2020 14:09:19 +0530
Subject: [PATCH 029/307] fix: child doctype naming
---
frappe/custom/doctype/package/package.js | 4 +-
frappe/custom/doctype/package/package.json | 18 ++---
frappe/custom/doctype/package/package.py | 19 ++++--
.../__init__.py | 0
.../package_detail/package_detail.json | 65 +++++++++++++++++++
.../package_detail.py} | 2 +-
.../package_doctype/package_doctype.json | 65 -------------------
.../release_instance/release_instance.json | 14 +---
8 files changed, 93 insertions(+), 94 deletions(-)
rename frappe/custom/doctype/{package_doctype => package_detail}/__init__.py (100%)
create mode 100644 frappe/custom/doctype/package_detail/package_detail.json
rename frappe/custom/doctype/{package_doctype/package_doctype.py => package_detail/package_detail.py} (88%)
delete mode 100644 frappe/custom/doctype/package_doctype/package_doctype.json
diff --git a/frappe/custom/doctype/package/package.js b/frappe/custom/doctype/package/package.js
index 54af424e4d..adad9d7e52 100644
--- a/frappe/custom/doctype/package/package.js
+++ b/frappe/custom/doctype/package/package.js
@@ -3,7 +3,7 @@
frappe.ui.form.on('Package', {
refresh: function(frm) {
- if (frm.doc.export_package) {
+ if (frm.doc.package_details) {
frm.add_custom_button(__("Go to Release"), function() {
frappe.set_route("Form", "Release", "Release");
});
@@ -22,7 +22,7 @@ frappe.ui.form.on('Package', {
}
});
-frappe.ui.form.on('Package DocType', {
+frappe.ui.form.on('Package Details', {
form_render: function (frm, cdt, cdn) {
function _show_filters(filters, table) {
table.find('tbody').empty();
diff --git a/frappe/custom/doctype/package/package.json b/frappe/custom/doctype/package/package.json
index 7bfdf719cf..0607abf6d7 100644
--- a/frappe/custom/doctype/package/package.json
+++ b/frappe/custom/doctype/package/package.json
@@ -5,19 +5,12 @@
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
- "export_package",
+ "package_details",
"import_section",
"attach",
"import"
],
"fields": [
- {
- "description": "Click on the row for accessing filters.",
- "fieldname": "export_package",
- "fieldtype": "Table",
- "label": "Package",
- "options": "Package DocType"
- },
{
"collapsible": 1,
"collapsible_depends_on": "attach",
@@ -34,11 +27,18 @@
"fieldname": "attach",
"fieldtype": "Attach",
"label": "Attach Package"
+ },
+ {
+ "description": "Click on the row for accessing filters.",
+ "fieldname": "package_details",
+ "fieldtype": "Table",
+ "label": "Package Details",
+ "options": "Package Detail"
}
],
"issingle": 1,
"links": [],
- "modified": "2020-03-19 22:03:06.012473",
+ "modified": "2020-04-06 14:32:42.202640",
"modified_by": "Administrator",
"module": "Custom",
"name": "Package",
diff --git a/frappe/custom/doctype/package/package.py b/frappe/custom/doctype/package/package.py
index a42de94896..ed9cb66957 100644
--- a/frappe/custom/doctype/package/package.py
+++ b/frappe/custom/doctype/package/package.py
@@ -33,7 +33,7 @@ def export_package():
package_doc = frappe.get_single("Package")
package = []
- for doctype in package_doc.export_package:
+ for doctype in package_doc.package_details:
filters = []
if doctype.get("filters_json"):
@@ -43,17 +43,28 @@ def export_package():
length = len(docs)
for idx, doc in enumerate(docs):
- frappe.publish_realtime("package", {"progress":idx, "total":length, "message":doctype.get("document_type"), "prefix": _("Exporting")},
+ frappe.publish_realtime("package", {
+ "progress":idx, "total":length,
+ "message":doctype.get("document_type"),
+ "prefix": _("Exporting")
+ },
user=frappe.session.user)
document = frappe.get_doc(doctype.get("document_type"), doc.name).as_dict()
attachments = []
if doctype.attachments:
- filters = {"attached_to_doctype": document.get("doctype"), "attached_to_name": document.get("name")}
+ filters = {
+ "attached_to_doctype": document.get("doctype"),
+ "attached_to_name": document.get("name")
+ }
+
for f in frappe.get_list("File", filters=filters):
fname, fcontents = get_file(f.name)
- attachments.append({"fname": fname, "content": base64.b64encode(fcontents).decode('ascii')})
+ attachments.append({
+ "fname": fname,
+ "content": base64.b64encode(fcontents).decode('ascii')
+ })
document.update({
"attachments": attachments,
diff --git a/frappe/custom/doctype/package_doctype/__init__.py b/frappe/custom/doctype/package_detail/__init__.py
similarity index 100%
rename from frappe/custom/doctype/package_doctype/__init__.py
rename to frappe/custom/doctype/package_detail/__init__.py
diff --git a/frappe/custom/doctype/package_detail/package_detail.json b/frappe/custom/doctype/package_detail/package_detail.json
new file mode 100644
index 0000000000..f749587a42
--- /dev/null
+++ b/frappe/custom/doctype/package_detail/package_detail.json
@@ -0,0 +1,65 @@
+{
+ "engine": "InnoDB",
+ "field_order": [
+ "document_type",
+ "column_break_2",
+ "attachments",
+ "overwrite",
+ "section_break_4",
+ "filters_json"
+ ],
+ "istable": 1,
+ "modified_by": "Administrator",
+ "name": "Package Detail",
+ "links": [],
+ "fields": [
+ {
+ "label": "Document Type",
+ "in_list_view": 1,
+ "fieldtype": "Link",
+ "reqd": 1,
+ "fieldname": "document_type",
+ "options": "DocType"
+ },
+ {
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break"
+ },
+ {
+ "default": "0",
+ "in_list_view": 1,
+ "fieldname": "attachments",
+ "fieldtype": "Check",
+ "label": "Include Attachments"
+ },
+ {
+ "default": "0",
+ "in_list_view": 1,
+ "fieldname": "overwrite",
+ "fieldtype": "Check",
+ "label": "Overwrite"
+ },
+ {
+ "fieldname": "section_break_4",
+ "fieldtype": "Section Break"
+ },
+ {
+ "options": "JSON",
+ "fieldname": "filters_json",
+ "fieldtype": "Code",
+ "label": "Filters"
+ }
+ ],
+ "track_changes": 1,
+ "creation": "2020-04-06 12:59:59.657816",
+ "doctype": "DocType",
+ "actions": [],
+ "modified": "2020-04-06 12:59:59.657816",
+ "sort_order": "DESC",
+ "module": "Custom",
+ "owner": "Administrator",
+ "sort_field": "modified",
+ "editable_grid": 1,
+ "quick_entry": 1,
+ "permissions": []
+}
\ No newline at end of file
diff --git a/frappe/custom/doctype/package_doctype/package_doctype.py b/frappe/custom/doctype/package_detail/package_detail.py
similarity index 88%
rename from frappe/custom/doctype/package_doctype/package_doctype.py
rename to frappe/custom/doctype/package_detail/package_detail.py
index c185395965..0460329d85 100644
--- a/frappe/custom/doctype/package_doctype/package_doctype.py
+++ b/frappe/custom/doctype/package_detail/package_detail.py
@@ -6,5 +6,5 @@ from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
-class PackageDocType(Document):
+class PackageDetail(Document):
pass
diff --git a/frappe/custom/doctype/package_doctype/package_doctype.json b/frappe/custom/doctype/package_doctype/package_doctype.json
deleted file mode 100644
index 058cff6480..0000000000
--- a/frappe/custom/doctype/package_doctype/package_doctype.json
+++ /dev/null
@@ -1,65 +0,0 @@
-{
- "actions": [],
- "creation": "2020-03-14 11:20:42.875446",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "document_type",
- "column_break_2",
- "attachments",
- "overwrite",
- "section_break_4",
- "filters_json"
- ],
- "fields": [
- {
- "fieldname": "document_type",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Document Type",
- "options": "DocType",
- "reqd": 1
- },
- {
- "fieldname": "filters_json",
- "fieldtype": "Code",
- "label": "Filters",
- "options": "JSON"
- },
- {
- "fieldname": "section_break_4",
- "fieldtype": "Section Break"
- },
- {
- "fieldname": "column_break_2",
- "fieldtype": "Column Break"
- },
- {
- "default": "0",
- "fieldname": "attachments",
- "fieldtype": "Check",
- "in_list_view": 1,
- "label": "Include Attachments"
- },
- {
- "default": "0",
- "fieldname": "overwrite",
- "fieldtype": "Check",
- "in_list_view": 1,
- "label": "Overwrite"
- }
- ],
- "istable": 1,
- "links": [],
- "modified": "2020-03-17 17:27:58.859896",
- "modified_by": "Administrator",
- "module": "Custom",
- "name": "Package DocType",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/frappe/custom/doctype/release_instance/release_instance.json b/frappe/custom/doctype/release_instance/release_instance.json
index d1bf07db59..90484b16f4 100644
--- a/frappe/custom/doctype/release_instance/release_instance.json
+++ b/frappe/custom/doctype/release_instance/release_instance.json
@@ -36,7 +36,7 @@
}
],
"links": [],
- "modified": "2020-03-18 18:54:55.801749",
+ "modified": "2020-04-06 14:31:49.443654",
"modified_by": "Administrator",
"module": "Custom",
"name": "Release Instance",
@@ -53,18 +53,6 @@
"role": "System Manager",
"share": 1,
"write": 1
- },
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "All",
- "share": 1,
- "write": 1
}
],
"quick_entry": 1,
From 1e7c4531e95e28b80cbacf65d2da6ce810ca1bd8 Mon Sep 17 00:00:00 2001
From: Saurabh
Date: Mon, 6 Apr 2020 14:52:20 +0530
Subject: [PATCH 030/307] fix: package overwriting
---
frappe/custom/doctype/package/package.py | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/frappe/custom/doctype/package/package.py b/frappe/custom/doctype/package/package.py
index ed9cb66957..0cdfe4a87e 100644
--- a/frappe/custom/doctype/package/package.py
+++ b/frappe/custom/doctype/package/package.py
@@ -91,14 +91,22 @@ def import_package(package=None):
d = frappe.get_doc(doc).insert(ignore_permissions=True, ignore_if_duplicate=True)
if attachments:
add_attachment(attachments, d)
- elif exists:
+ else:
docname = doc.pop("name")
document = frappe.get_doc(doc.get("doctype"), docname)
- if frappe.utils.get_datetime(document.modified) < frappe.utils.get_datetime(modified) and not overwrite:
- document.update(doc)
- document.save()
- if attachments:
- add_attachment(attachments, document)
+
+ if overwrite:
+ update_document(document, doc, attachments)
+
+ else:
+ if frappe.utils.get_datetime(document.modified) < frappe.utils.get_datetime(modified):
+ update_document(document, doc, attachments)
+
+def update_document(document, doc, attachments):
+ document.update(doc)
+ document.save()
+ if attachments:
+ add_attachment(attachments, document)
def add_attachment(attachments, doc):
for attachment in attachments:
From 514f2bdae998b1bb5b37b90409b31086828252fa Mon Sep 17 00:00:00 2001
From: Saurabh
Date: Mon, 6 Apr 2020 15:32:44 +0530
Subject: [PATCH 031/307] fix: rename release related doctypes
---
frappe/custom/doctype/package/package.js | 2 +-
frappe/custom/doctype/release/release.json | 4 +-
frappe/custom/doctype/release/release.py | 2 +-
.../release_instance/release_instance.js | 8 ----
.../release_instance/release_instance.json | 48 ++++---------------
.../release_instance/test_release_instance.py | 10 ----
.../doctype/release_instance_list/__init__.py | 0
.../release_instance_list.json | 32 -------------
.../release_instance_list.py | 10 ----
9 files changed, 13 insertions(+), 103 deletions(-)
delete mode 100644 frappe/custom/doctype/release_instance/release_instance.js
delete mode 100644 frappe/custom/doctype/release_instance/test_release_instance.py
delete mode 100644 frappe/custom/doctype/release_instance_list/__init__.py
delete mode 100644 frappe/custom/doctype/release_instance_list/release_instance_list.json
delete mode 100644 frappe/custom/doctype/release_instance_list/release_instance_list.py
diff --git a/frappe/custom/doctype/package/package.js b/frappe/custom/doctype/package/package.js
index adad9d7e52..1743f38dd3 100644
--- a/frappe/custom/doctype/package/package.js
+++ b/frappe/custom/doctype/package/package.js
@@ -9,7 +9,7 @@ frappe.ui.form.on('Package', {
});
}
- frm.set_query("document_type", "export_package", function () {
+ frm.set_query("document_type", "package_details", function () {
return {
filters: {
"istable": 0,
diff --git a/frappe/custom/doctype/release/release.json b/frappe/custom/doctype/release/release.json
index ba6c69c49f..b3f44196d0 100644
--- a/frappe/custom/doctype/release/release.json
+++ b/frappe/custom/doctype/release/release.json
@@ -12,12 +12,12 @@
"fieldname": "instances",
"fieldtype": "Table",
"label": "Instances",
- "options": "Release Instance List"
+ "options": "Release Instance"
}
],
"issingle": 1,
"links": [],
- "modified": "2020-03-18 18:25:23.539372",
+ "modified": "2020-04-06 14:56:56.206720",
"modified_by": "Administrator",
"module": "Custom",
"name": "Release",
diff --git a/frappe/custom/doctype/release/release.py b/frappe/custom/doctype/release/release.py
index e68be15778..c02aa0605d 100644
--- a/frappe/custom/doctype/release/release.py
+++ b/frappe/custom/doctype/release/release.py
@@ -32,7 +32,7 @@ class Release(Document):
self.install_package_to_remote(package, instance)
def install_package_to_remote(self, package, instance):
- remote = frappe.get_doc("Release Instance", instance.instance)
+ remote = frappe.get_doc("Instance", instance.instance)
try:
connection = FrappeClient(remote.instance, remote.user, get_decrypted_password(remote.doctype, remote.name))
diff --git a/frappe/custom/doctype/release_instance/release_instance.js b/frappe/custom/doctype/release_instance/release_instance.js
deleted file mode 100644
index 7447c9c706..0000000000
--- a/frappe/custom/doctype/release_instance/release_instance.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2020, Frappe Technologies and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Release Instance', {
- // refresh: function(frm) {
-
- // }
-});
diff --git a/frappe/custom/doctype/release_instance/release_instance.json b/frappe/custom/doctype/release_instance/release_instance.json
index 90484b16f4..2ebdc93954 100644
--- a/frappe/custom/doctype/release_instance/release_instance.json
+++ b/frappe/custom/doctype/release_instance/release_instance.json
@@ -1,60 +1,30 @@
{
"actions": [],
- "autoname": "field:instance",
- "creation": "2020-03-17 12:24:29.615432",
+ "creation": "2020-03-18 18:25:02.024237",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
- "instance",
- "user",
- "password"
+ "instance"
],
"fields": [
{
"fieldname": "instance",
- "fieldtype": "Data",
+ "fieldtype": "Link",
"in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Instance URL",
- "unique": 1
- },
- {
- "fieldname": "user",
- "fieldtype": "Data",
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "User",
- "options": "Email"
- },
- {
- "fieldname": "password",
- "fieldtype": "Password",
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Password"
+ "label": "Instance",
+ "options": "Instance",
+ "reqd": 1
}
],
+ "istable": 1,
"links": [],
- "modified": "2020-04-06 14:31:49.443654",
+ "modified": "2020-04-06 15:30:08.966941",
"modified_by": "Administrator",
"module": "Custom",
"name": "Release Instance",
"owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "share": 1,
- "write": 1
- }
- ],
+ "permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
diff --git a/frappe/custom/doctype/release_instance/test_release_instance.py b/frappe/custom/doctype/release_instance/test_release_instance.py
deleted file mode 100644
index 95df304262..0000000000
--- a/frappe/custom/doctype/release_instance/test_release_instance.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2020, Frappe Technologies and Contributors
-# See license.txt
-from __future__ import unicode_literals
-
-# import frappe
-import unittest
-
-class TestReleaseInstance(unittest.TestCase):
- pass
diff --git a/frappe/custom/doctype/release_instance_list/__init__.py b/frappe/custom/doctype/release_instance_list/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/frappe/custom/doctype/release_instance_list/release_instance_list.json b/frappe/custom/doctype/release_instance_list/release_instance_list.json
deleted file mode 100644
index d9b9b63340..0000000000
--- a/frappe/custom/doctype/release_instance_list/release_instance_list.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "actions": [],
- "creation": "2020-03-18 18:25:02.024237",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "instance"
- ],
- "fields": [
- {
- "fieldname": "instance",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Instance",
- "options": "Release Instance",
- "reqd": 1
- }
- ],
- "istable": 1,
- "links": [],
- "modified": "2020-03-18 22:55:20.130597",
- "modified_by": "Administrator",
- "module": "Custom",
- "name": "Release Instance List",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/frappe/custom/doctype/release_instance_list/release_instance_list.py b/frappe/custom/doctype/release_instance_list/release_instance_list.py
deleted file mode 100644
index f6eb68a535..0000000000
--- a/frappe/custom/doctype/release_instance_list/release_instance_list.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2020, Frappe Technologies and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-# import frappe
-from frappe.model.document import Document
-
-class ReleaseInstanceList(Document):
- pass
From 23a76cea202588b6d450057cba7a454837f035cd Mon Sep 17 00:00:00 2001
From: Saurabh
Date: Mon, 6 Apr 2020 15:42:16 +0530
Subject: [PATCH 032/307] fix: rename instance to deploy instance
---
.../doctype/deploy_instance/__init__.py | 0
.../deploy_instance/deploy_instance.js | 8 +++
.../deploy_instance/deploy_instance.json | 63 +++++++++++++++++++
.../deploy_instance/deploy_instance.py | 10 +++
.../deploy_instance/test_deploy_instance.py | 10 +++
frappe/custom/doctype/release/release.py | 2 +-
.../release_instance/release_instance.json | 4 +-
7 files changed, 94 insertions(+), 3 deletions(-)
create mode 100644 frappe/custom/doctype/deploy_instance/__init__.py
create mode 100644 frappe/custom/doctype/deploy_instance/deploy_instance.js
create mode 100644 frappe/custom/doctype/deploy_instance/deploy_instance.json
create mode 100644 frappe/custom/doctype/deploy_instance/deploy_instance.py
create mode 100644 frappe/custom/doctype/deploy_instance/test_deploy_instance.py
diff --git a/frappe/custom/doctype/deploy_instance/__init__.py b/frappe/custom/doctype/deploy_instance/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frappe/custom/doctype/deploy_instance/deploy_instance.js b/frappe/custom/doctype/deploy_instance/deploy_instance.js
new file mode 100644
index 0000000000..d4b6e75155
--- /dev/null
+++ b/frappe/custom/doctype/deploy_instance/deploy_instance.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, Frappe Technologies and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('DeployInstance', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/frappe/custom/doctype/deploy_instance/deploy_instance.json b/frappe/custom/doctype/deploy_instance/deploy_instance.json
new file mode 100644
index 0000000000..2822ab81f9
--- /dev/null
+++ b/frappe/custom/doctype/deploy_instance/deploy_instance.json
@@ -0,0 +1,63 @@
+{
+ "actions": [],
+ "autoname": "field:instance",
+ "creation": "2020-04-06 15:34:44.428007",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "instance",
+ "user",
+ "password"
+ ],
+ "fields": [
+ {
+ "fieldname": "instance",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Instance URL",
+ "unique": 1
+ },
+ {
+ "fieldname": "user",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "User",
+ "options": "Email"
+ },
+ {
+ "fieldname": "password",
+ "fieldtype": "Password",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Password"
+ }
+ ],
+ "links": [],
+ "modified": "2020-04-06 15:40:39.242881",
+ "modified_by": "Administrator",
+ "module": "Custom",
+ "name": "Deploy Instance",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_views": 1
+}
\ No newline at end of file
diff --git a/frappe/custom/doctype/deploy_instance/deploy_instance.py b/frappe/custom/doctype/deploy_instance/deploy_instance.py
new file mode 100644
index 0000000000..9bc2e9192e
--- /dev/null
+++ b/frappe/custom/doctype/deploy_instance/deploy_instance.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class DeployInstance(Document):
+ pass
diff --git a/frappe/custom/doctype/deploy_instance/test_deploy_instance.py b/frappe/custom/doctype/deploy_instance/test_deploy_instance.py
new file mode 100644
index 0000000000..cdacc3a1ca
--- /dev/null
+++ b/frappe/custom/doctype/deploy_instance/test_deploy_instance.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestDeployInstance(unittest.TestCase):
+ pass
diff --git a/frappe/custom/doctype/release/release.py b/frappe/custom/doctype/release/release.py
index c02aa0605d..05b99f3e57 100644
--- a/frappe/custom/doctype/release/release.py
+++ b/frappe/custom/doctype/release/release.py
@@ -32,7 +32,7 @@ class Release(Document):
self.install_package_to_remote(package, instance)
def install_package_to_remote(self, package, instance):
- remote = frappe.get_doc("Instance", instance.instance)
+ remote = frappe.get_doc("Deploy Instance", instance.instance)
try:
connection = FrappeClient(remote.instance, remote.user, get_decrypted_password(remote.doctype, remote.name))
diff --git a/frappe/custom/doctype/release_instance/release_instance.json b/frappe/custom/doctype/release_instance/release_instance.json
index 2ebdc93954..4ac4f30246 100644
--- a/frappe/custom/doctype/release_instance/release_instance.json
+++ b/frappe/custom/doctype/release_instance/release_instance.json
@@ -13,13 +13,13 @@
"fieldtype": "Link",
"in_list_view": 1,
"label": "Instance",
- "options": "Instance",
+ "options": "Deploy Instance",
"reqd": 1
}
],
"istable": 1,
"links": [],
- "modified": "2020-04-06 15:30:08.966941",
+ "modified": "2020-04-06 15:37:07.099322",
"modified_by": "Administrator",
"module": "Custom",
"name": "Release Instance",
From 08d7f905b57060ae4d6418ee2e681bef4830e96e Mon Sep 17 00:00:00 2001
From: Saurabh
Date: Wed, 15 Apr 2020 16:36:41 +0530
Subject: [PATCH 033/307] feat: provision to deploy packages
---
.../deploy_instance/deploy_instance.json | 45 ++++++-----------
frappe/custom/doctype/package/package.js | 24 ++++++---
frappe/custom/doctype/package/package.json | 14 +++++-
frappe/custom/doctype/package/package.py | 37 +++++++++++++-
frappe/custom/doctype/release/__init__.py | 0
frappe/custom/doctype/release/release.js | 23 ---------
frappe/custom/doctype/release/release.json | 41 ---------------
frappe/custom/doctype/release/release.py | 50 -------------------
frappe/custom/doctype/release/test_release.py | 10 ----
.../doctype/release_instance/__init__.py | 0
.../release_instance/release_instance.json | 32 ------------
.../release_instance/release_instance.py | 10 ----
12 files changed, 80 insertions(+), 206 deletions(-)
delete mode 100644 frappe/custom/doctype/release/__init__.py
delete mode 100644 frappe/custom/doctype/release/release.js
delete mode 100644 frappe/custom/doctype/release/release.json
delete mode 100644 frappe/custom/doctype/release/release.py
delete mode 100644 frappe/custom/doctype/release/test_release.py
delete mode 100644 frappe/custom/doctype/release_instance/__init__.py
delete mode 100644 frappe/custom/doctype/release_instance/release_instance.json
delete mode 100644 frappe/custom/doctype/release_instance/release_instance.py
diff --git a/frappe/custom/doctype/deploy_instance/deploy_instance.json b/frappe/custom/doctype/deploy_instance/deploy_instance.json
index 2822ab81f9..4bb140f088 100644
--- a/frappe/custom/doctype/deploy_instance/deploy_instance.json
+++ b/frappe/custom/doctype/deploy_instance/deploy_instance.json
@@ -1,63 +1,46 @@
{
"actions": [],
- "autoname": "field:instance",
- "creation": "2020-04-06 15:34:44.428007",
+ "creation": "2020-03-18 18:25:02.024237",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
- "instance",
- "user",
+ "instance_url",
+ "username",
"password"
],
"fields": [
{
- "fieldname": "instance",
+ "fieldname": "instance_url",
"fieldtype": "Data",
"in_list_view": 1,
- "in_standard_filter": 1,
"label": "Instance URL",
- "unique": 1
+ "reqd": 1
},
{
- "fieldname": "user",
+ "fieldname": "username",
"fieldtype": "Data",
"in_list_view": 1,
- "in_standard_filter": 1,
- "label": "User",
- "options": "Email"
+ "label": "Username",
+ "reqd": 1
},
{
"fieldname": "password",
"fieldtype": "Password",
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Password"
+ "label": "Password",
+ "reqd": 1
}
],
+ "istable": 1,
"links": [],
- "modified": "2020-04-06 15:40:39.242881",
+ "modified": "2020-04-14 13:56:31.167730",
"modified_by": "Administrator",
"module": "Custom",
"name": "Deploy Instance",
"owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "share": 1,
- "write": 1
- }
- ],
+ "permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
- "track_changes": 1,
- "track_views": 1
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/frappe/custom/doctype/package/package.js b/frappe/custom/doctype/package/package.js
index 1743f38dd3..47a7bce0df 100644
--- a/frappe/custom/doctype/package/package.js
+++ b/frappe/custom/doctype/package/package.js
@@ -3,12 +3,6 @@
frappe.ui.form.on('Package', {
refresh: function(frm) {
- if (frm.doc.package_details) {
- frm.add_custom_button(__("Go to Release"), function() {
- frappe.set_route("Form", "Release", "Release");
- });
- }
-
frm.set_query("document_type", "package_details", function () {
return {
filters: {
@@ -16,13 +10,29 @@ frappe.ui.form.on('Package', {
}
};
});
+
+ frappe.realtime.on("package", (data) => {
+ frm.dashboard.show_progress(data.prefix, data.progress / data.total * 100, __("{0}", [data.message]));
+ if ((data.progress+1) != data.total) {
+ frm.dashboard.show_progress(data.prefix, data.progress / data.total * 100, __("{0}", [data.message]));
+ } else {
+ frm.dashboard.hide_progress();
+ }
+ });
+
+ if(frm.doc.instances){
+ frm.add_custom_button(__("Deploy"), function() {
+ frm.call("deploy_package");
+ });
+ }
+
},
import: function(frm) {
frm.call("import_from_package");
}
});
-frappe.ui.form.on('Package Details', {
+frappe.ui.form.on('Package Detail', {
form_render: function (frm, cdt, cdn) {
function _show_filters(filters, table) {
table.find('tbody').empty();
diff --git a/frappe/custom/doctype/package/package.json b/frappe/custom/doctype/package/package.json
index 0607abf6d7..2bec7f9b79 100644
--- a/frappe/custom/doctype/package/package.json
+++ b/frappe/custom/doctype/package/package.json
@@ -6,6 +6,8 @@
"engine": "InnoDB",
"field_order": [
"package_details",
+ "section_break_2",
+ "instances",
"import_section",
"attach",
"import"
@@ -34,11 +36,21 @@
"fieldtype": "Table",
"label": "Package Details",
"options": "Package Detail"
+ },
+ {
+ "fieldname": "section_break_2",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "instances",
+ "fieldtype": "Table",
+ "label": "Instances",
+ "options": "Deploy Instance"
}
],
"issingle": 1,
"links": [],
- "modified": "2020-04-06 14:32:42.202640",
+ "modified": "2020-04-14 13:50:50.779396",
"modified_by": "Administrator",
"module": "Custom",
"name": "Package",
diff --git a/frappe/custom/doctype/package/package.py b/frappe/custom/doctype/package/package.py
index 0cdfe4a87e..b4427d55bc 100644
--- a/frappe/custom/doctype/package/package.py
+++ b/frappe/custom/doctype/package/package.py
@@ -11,9 +11,11 @@ from frappe.model.document import Document
from frappe.utils.file_manager import save_file, get_file
from frappe import _
from six import string_types
+from frappe.frappeclient import FrappeClient
+from frappe.model.naming import make_autoname
+from frappe.utils.password import get_decrypted_password
class Package(Document):
-
def import_from_package(self):
filters = {"attached_to_doctype": "Package", "attached_to_name": "Package"}
files = frappe.get_list("File", filters=filters, limit=1, order_by="creation desc")
@@ -27,6 +29,39 @@ class Package(Document):
frappe.msgprint(_("Package Imported."))
+ def deploy_package(self):
+ package = export_package()
+
+ for dt_file in frappe.get_list("File", filters={"attached_to_doctype": "Release", "attached_to_name": "Release"}):
+ frappe.delete_doc_if_exists("File", dt_file.name)
+
+ file_name = make_autoname("Package")
+ save_file(file_name, json.dumps(package), "Package", "Package")
+
+ length = len(self.instances)
+ for idx, instance in enumerate(self.instances):
+ frappe.publish_realtime("package", {"progress": idx, "total": length, "message": instance.instance_url, "prefix": _("Deploying")},
+ user=frappe.session.user)
+
+ self.install_package_to_remote(package, instance)
+
+ def install_package_to_remote(self, package, instance):
+ print((instance.doctype, instance.name))
+ try:
+ connection = FrappeClient(instance.instance_url, instance.username, get_decrypted_password(instance.doctype, instance.name))
+ except Exception:
+ frappe.log_error(frappe.get_traceback())
+ frappe.throw(_("Couldn't connect to site {0}. Please check Error Logs.").format(instance.instance_url))
+
+ try:
+ connection.post_request({
+ "cmd": "frappe.custom.doctype.package.package.import_package",
+ "package": json.dumps(package)
+ })
+ except Exception:
+ frappe.log_error(frappe.get_traceback())
+ frappe.throw(_("Error while installing package to site {0}. Please check Error Logs.").format(instance.instance_url))
+
@frappe.whitelist()
def export_package():
"""Export package as JSON."""
diff --git a/frappe/custom/doctype/release/__init__.py b/frappe/custom/doctype/release/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/frappe/custom/doctype/release/release.js b/frappe/custom/doctype/release/release.js
deleted file mode 100644
index 709ae18d36..0000000000
--- a/frappe/custom/doctype/release/release.js
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2020, Frappe Technologies and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Release', {
- refresh: function(frm) {
- frm.add_custom_button(__("Go to Package"), function() {
- frappe.set_route("Form", "Package", "Package");
- });
-
- frm.add_custom_button(__("Release"), function() {
- frm.call("create_release");
- });
-
- frappe.realtime.on("package", (data) => {
- frm.dashboard.show_progress(data.prefix, data.progress / data.total * 100, __("{0}", [data.message]));
- if ((data.progress+1) != data.total) {
- frm.dashboard.show_progress(data.prefix, data.progress / data.total * 100, __("{0}", [data.message]));
- } else {
- frm.dashboard.hide_progress();
- }
- });
- }
-});
diff --git a/frappe/custom/doctype/release/release.json b/frappe/custom/doctype/release/release.json
deleted file mode 100644
index b3f44196d0..0000000000
--- a/frappe/custom/doctype/release/release.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
- "actions": [],
- "creation": "2020-03-17 13:27:30.158389",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "instances"
- ],
- "fields": [
- {
- "fieldname": "instances",
- "fieldtype": "Table",
- "label": "Instances",
- "options": "Release Instance"
- }
- ],
- "issingle": 1,
- "links": [],
- "modified": "2020-04-06 14:56:56.206720",
- "modified_by": "Administrator",
- "module": "Custom",
- "name": "Release",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "print": 1,
- "read": 1,
- "role": "System Manager",
- "share": 1,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/frappe/custom/doctype/release/release.py b/frappe/custom/doctype/release/release.py
deleted file mode 100644
index 05b99f3e57..0000000000
--- a/frappe/custom/doctype/release/release.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2020, Frappe Technologies and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-import frappe
-import json
-from frappe import _
-from frappe.model.document import Document
-from frappe.custom.doctype.package.package import export_package
-from frappe.frappeclient import FrappeClient
-from frappe.utils.file_manager import save_file
-from frappe.model.naming import make_autoname
-from frappe.utils.password import get_decrypted_password
-
-class Release(Document):
-
- def create_release(self):
- package = export_package()
-
- for dt_file in frappe.get_list("File", filters={"attached_to_doctype": "Release", "attached_to_name": "Release"}):
- frappe.delete_doc_if_exists("File", dt_file.name)
-
- file_name = make_autoname("Package")
- save_file(file_name, json.dumps(package), "Release", "Release")
-
- length = len(self.instances)
- for idx, instance in enumerate(self.instances):
- frappe.publish_realtime("package", {"progress": idx, "total": length, "message": instance.instance, "prefix": _("Deploying")},
- user=frappe.session.user)
-
- self.install_package_to_remote(package, instance)
-
- def install_package_to_remote(self, package, instance):
- remote = frappe.get_doc("Deploy Instance", instance.instance)
-
- try:
- connection = FrappeClient(remote.instance, remote.user, get_decrypted_password(remote.doctype, remote.name))
- except Exception:
- frappe.log_error(frappe.get_traceback())
- frappe.throw(_("Couldn't connect to site {0}. Please check Error Logs.").format(remote.instance))
-
- try:
- connection.post_request({
- "cmd": "frappe.custom.doctype.package.package.import_package",
- "package": json.dumps(package)
- })
- except Exception:
- frappe.log_error(frappe.get_traceback())
- frappe.throw(_("Error while installing package to site {0}. Please check Error Logs.").format(remote.instance))
diff --git a/frappe/custom/doctype/release/test_release.py b/frappe/custom/doctype/release/test_release.py
deleted file mode 100644
index 13e4e26ac0..0000000000
--- a/frappe/custom/doctype/release/test_release.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2020, Frappe Technologies and Contributors
-# See license.txt
-from __future__ import unicode_literals
-
-# import frappe
-import unittest
-
-class TestRelease(unittest.TestCase):
- pass
diff --git a/frappe/custom/doctype/release_instance/__init__.py b/frappe/custom/doctype/release_instance/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/frappe/custom/doctype/release_instance/release_instance.json b/frappe/custom/doctype/release_instance/release_instance.json
deleted file mode 100644
index 4ac4f30246..0000000000
--- a/frappe/custom/doctype/release_instance/release_instance.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "actions": [],
- "creation": "2020-03-18 18:25:02.024237",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "instance"
- ],
- "fields": [
- {
- "fieldname": "instance",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Instance",
- "options": "Deploy Instance",
- "reqd": 1
- }
- ],
- "istable": 1,
- "links": [],
- "modified": "2020-04-06 15:37:07.099322",
- "modified_by": "Administrator",
- "module": "Custom",
- "name": "Release Instance",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/frappe/custom/doctype/release_instance/release_instance.py b/frappe/custom/doctype/release_instance/release_instance.py
deleted file mode 100644
index f5b745a9b4..0000000000
--- a/frappe/custom/doctype/release_instance/release_instance.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2020, Frappe Technologies and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-# import frappe
-from frappe.model.document import Document
-
-class ReleaseInstance(Document):
- pass
From 2ed2e9f98b6e226f770794b18657b7456d9ed6c9 Mon Sep 17 00:00:00 2001
From: snyk-bot
Date: Fri, 1 May 2020 04:32:34 +0530
Subject: [PATCH 034/307] fix: .snyk & package.json to reduce vulnerabilities
The following vulnerabilities are fixed with a Snyk patch:
- https://snyk.io/vuln/SNYK-JS-LODASH-567746
---
.snyk | 43 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/.snyk b/.snyk
index b39169dcee..0dfecc6136 100644
--- a/.snyk
+++ b/.snyk
@@ -1,5 +1,5 @@
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
-version: v1.13.5
+version: v1.14.1
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
ignore:
SNYK-JS-AWESOMPLETE-174474:
@@ -22,3 +22,44 @@ patch:
SNYK-JS-LODASH-450202:
- frappe-datatable > lodash:
patched: '2020-01-31T01:33:09.889Z'
+ SNYK-JS-LODASH-567746:
+ - frappe-datatable > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - quagga > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - tailwindcss > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - '@tailwindcss/ui > @tailwindcss/custom-forms > lodash':
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > @snyk/dep-graph > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > inquirer > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > snyk-config > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > snyk-mvn-plugin > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > snyk-nodejs-lockfile-parser > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > snyk-nuget-plugin > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > @snyk/dep-graph > graphlib > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > snyk-go-plugin > graphlib > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > snyk-nodejs-lockfile-parser > graphlib > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > @snyk/snyk-cocoapods-plugin > @snyk/dep-graph > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > snyk-nuget-plugin > dotnet-deps-parser > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > snyk-php-plugin > @snyk/composer-lockfile-parser > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > @snyk/snyk-cocoapods-plugin > @snyk/dep-graph > graphlib > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > @snyk/snyk-cocoapods-plugin > @snyk/cocoapods-lockfile-parser > @snyk/ruby-semver > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
+ - snyk > @snyk/snyk-cocoapods-plugin > @snyk/cocoapods-lockfile-parser > @snyk/dep-graph > graphlib > lodash:
+ patched: '2020-04-30T23:02:32.330Z'
From d11463dfd65b26f6198ade410224e6f970d5e5ef Mon Sep 17 00:00:00 2001
From: snyk-bot
Date: Fri, 1 May 2020 04:32:35 +0530
Subject: [PATCH 035/307] fix: .snyk & package.json to reduce vulnerabilities
The following vulnerabilities are fixed with a Snyk patch:
- https://snyk.io/vuln/SNYK-JS-LODASH-567746
---
package.json | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/package.json b/package.json
index e735beee9b..583a9a00d3 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,8 @@
"production": "FRAPPE_ENV=production node rollup/build.js",
"watch": "node rollup/watch.js",
"cypress:open": "cypress open",
- "snyk-protect": "snyk protect"
+ "snyk-protect": "snyk protect",
+ "prepare": "yarn run snyk-protect"
},
"repository": {
"type": "git",
@@ -42,7 +43,7 @@
"qz-tray": "^2.0.8",
"redis": "^2.8.0",
"showdown": "^1.9.1",
- "snyk": "^1.297.4",
+ "snyk": "^1.316.1",
"socket.io": "^2.3.0",
"superagent": "^3.8.2",
"tailwindcss": "^1.3.3",
From b7408102411e4375aa1a155b3ee2bc809782aebc Mon Sep 17 00:00:00 2001
From: Mangesh-Khairnar
Date: Mon, 4 May 2020 14:00:14 +0530
Subject: [PATCH 036/307] feat(blog settings): social share settings
---
.../doctype/blog_settings/blog_settings.json | 182 ++++++------------
.../doctype/social_link_settings/__init__.py | 0
.../social_link_settings.json | 43 +++++
.../social_link_settings.py | 10 +
4 files changed, 107 insertions(+), 128 deletions(-)
create mode 100644 frappe/website/doctype/social_link_settings/__init__.py
create mode 100644 frappe/website/doctype/social_link_settings/social_link_settings.json
create mode 100644 frappe/website/doctype/social_link_settings/social_link_settings.py
diff --git a/frappe/website/doctype/blog_settings/blog_settings.json b/frappe/website/doctype/blog_settings/blog_settings.json
index 1ee974d850..f0e51de170 100644
--- a/frappe/website/doctype/blog_settings/blog_settings.json
+++ b/frappe/website/doctype/blog_settings/blog_settings.json
@@ -1,139 +1,65 @@
{
- "allow_copy": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2013-03-11 17:48:16",
- "custom": 0,
- "description": "Blog Settings",
- "docstatus": 0,
- "doctype": "DocType",
- "editable_grid": 0,
+ "actions": [],
+ "creation": "2013-03-11 17:48:16",
+ "description": "Blog Settings",
+ "doctype": "DocType",
+ "engine": "InnoDB",
+ "field_order": [
+ "blog_title",
+ "blog_introduction",
+ "writers_introduction",
+ "section_break_4",
+ "social_share_settings"
+ ],
"fields": [
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "blog_title",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Blog Title",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "blog_title",
+ "fieldtype": "Data",
+ "label": "Blog Title"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "blog_introduction",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Blog Introduction",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "blog_introduction",
+ "fieldtype": "Small Text",
+ "label": "Blog Introduction"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "writers_introduction",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Writers Introduction",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
+ "fieldname": "writers_introduction",
+ "fieldtype": "Small Text",
+ "label": "Writers Introduction"
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "section_break_4",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "social_share_settings",
+ "fieldtype": "Table",
+ "label": "Social Share Settings",
+ "options": "Social Link Settings"
}
- ],
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-cog",
- "idx": 1,
- "image_view": 0,
- "in_create": 0,
-
- "is_submittable": 0,
- "issingle": 1,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2016-12-29 14:40:41.629468",
- "modified_by": "Administrator",
- "module": "Website",
- "name": "Blog Settings",
- "owner": "Administrator",
+ ],
+ "icon": "fa fa-cog",
+ "idx": 1,
+ "issingle": 1,
+ "links": [],
+ "modified": "2020-05-04 09:10:41.815238",
+ "modified_by": "Administrator",
+ "module": "Website",
+ "name": "Blog Settings",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "is_custom": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 0,
- "role": "Website Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "role": "Website Manager",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "track_changes": 1,
- "track_seen": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/frappe/website/doctype/social_link_settings/__init__.py b/frappe/website/doctype/social_link_settings/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frappe/website/doctype/social_link_settings/social_link_settings.json b/frappe/website/doctype/social_link_settings/social_link_settings.json
new file mode 100644
index 0000000000..459c98eed6
--- /dev/null
+++ b/frappe/website/doctype/social_link_settings/social_link_settings.json
@@ -0,0 +1,43 @@
+{
+ "actions": [],
+ "creation": "2020-04-30 07:39:33.095554",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "social_link_type",
+ "color",
+ "background_color"
+ ],
+ "fields": [
+ {
+ "fieldname": "social_link_type",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Social Link Type",
+ "options": "\nfacebook\nlinkedin\ntwitter\nemail"
+ },
+ {
+ "fieldname": "color",
+ "fieldtype": "Color",
+ "in_list_view": 1,
+ "label": "Color"
+ },
+ {
+ "fieldname": "background_color",
+ "fieldtype": "Color",
+ "in_list_view": 1,
+ "label": "Background Color"
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-05-01 23:55:04.731518",
+ "modified_by": "Administrator",
+ "module": "Website",
+ "name": "Social Link Settings",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/frappe/website/doctype/social_link_settings/social_link_settings.py b/frappe/website/doctype/social_link_settings/social_link_settings.py
new file mode 100644
index 0000000000..b382afac99
--- /dev/null
+++ b/frappe/website/doctype/social_link_settings/social_link_settings.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class SocialLinkSettings(Document):
+ pass
From ef3e3685e90449f3379102833f40d6c7d6a50674 Mon Sep 17 00:00:00 2001
From: Mangesh-Khairnar
Date: Mon, 4 May 2020 18:01:14 +0530
Subject: [PATCH 037/307] feat(about): add social media links
---
frappe/public/js/frappe/ui/toolbar/about.js | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/frappe/public/js/frappe/ui/toolbar/about.js b/frappe/public/js/frappe/ui/toolbar/about.js
index 13ba4836fb..87462916c2 100644
--- a/frappe/public/js/frappe/ui/toolbar/about.js
+++ b/frappe/public/js/frappe/ui/toolbar/about.js
@@ -9,6 +9,12 @@ frappe.ui.misc.about = function() {
Website: https://frappe.io
\
\
Source: https://github.com/frappe
\
+ \
+ Linkedin: https://linkedin.com/company/frappe-tech
\
+ \
+ Facebook: https://facebook.com/erpnext
\
+ \
+ Twitter: https://twitter.com/erpnext
\
\
Installed Apps
\
Loading versions...
\
From 77d2c3d8cfaaa61aa7c8984f6e5ec3640c6ab020 Mon Sep 17 00:00:00 2001
From: Shivam Mishra
Date: Tue, 5 May 2020 13:43:34 +0530
Subject: [PATCH 038/307] feat: added patch for is unique
---
frappe/patches.txt | 1 +
.../patches/v13_0/set_unique_for_page_view.py | 6 +++++
.../doctype/web_page_view/web_page_view.json | 24 ++++++++++++++-----
3 files changed, 25 insertions(+), 6 deletions(-)
create mode 100644 frappe/patches/v13_0/set_unique_for_page_view.py
diff --git a/frappe/patches.txt b/frappe/patches.txt
index a086fa6f4a..3d8b0732d2 100644
--- a/frappe/patches.txt
+++ b/frappe/patches.txt
@@ -278,3 +278,4 @@ frappe.patches.v13_0.set_path_for_homepage_in_web_page_view
frappe.patches.v13_0.migrate_translation_column_data
frappe.patches.v13_0.set_read_times
frappe.patches.v13_0.remove_web_view
+frappe.patches.v13_0.set_unique_for_page_view
\ No newline at end of file
diff --git a/frappe/patches/v13_0/set_unique_for_page_view.py b/frappe/patches/v13_0/set_unique_for_page_view.py
new file mode 100644
index 0000000000..2a084e52e3
--- /dev/null
+++ b/frappe/patches/v13_0/set_unique_for_page_view.py
@@ -0,0 +1,6 @@
+import frappe
+
+def execute():
+ frappe.reload_doc('website', 'doctype', 'web_page_view', force=True)
+ site_url = frappe.utils.get_site_url(frappe.local.site)
+ frappe.db.sql("""UPDATE `tabWeb Page View` set is_unique=1 where referrer LIKE '%{0}%'""".format(site_url))
diff --git a/frappe/website/doctype/web_page_view/web_page_view.json b/frappe/website/doctype/web_page_view/web_page_view.json
index 7a1a210d62..4243df39b1 100644
--- a/frappe/website/doctype/web_page_view/web_page_view.json
+++ b/frappe/website/doctype/web_page_view/web_page_view.json
@@ -1,5 +1,6 @@
{
"actions": [],
+ "allow_import": 1,
"creation": "2020-04-15 22:54:46.009703",
"doctype": "DocType",
"editable_grid": 1,
@@ -9,7 +10,9 @@
"referrer",
"browser",
"browser_version",
- "date"
+ "is_unique",
+ "time_zone",
+ "user_agent"
],
"fields": [
{
@@ -39,15 +42,24 @@
"set_only_once": 1
},
{
- "fieldname": "date",
- "fieldtype": "Datetime",
- "label": "Date",
- "set_only_once": 1
+ "fieldname": "is_unique",
+ "fieldtype": "Data",
+ "label": "Is Unique"
+ },
+ {
+ "fieldname": "time_zone",
+ "fieldtype": "Data",
+ "label": "Time Zone"
+ },
+ {
+ "fieldname": "user_agent",
+ "fieldtype": "Data",
+ "label": "User Agent"
}
],
"in_create": 1,
"links": [],
- "modified": "2020-04-15 23:31:27.517793",
+ "modified": "2020-05-05 14:11:24.718770",
"modified_by": "Administrator",
"module": "Website",
"name": "Web Page View",
From ab9e596f627dc70dab273d1b8485796559ea23a3 Mon Sep 17 00:00:00 2001
From: Shivam Mishra
Date: Tue, 5 May 2020 15:06:14 +0530
Subject: [PATCH 039/307] feat: do not track 404
---
frappe/www/404.html | 6 ++++--
frappe/www/website_script.js | 2 +-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/frappe/www/404.html b/frappe/www/404.html
index 47685c45d0..dc178dbdc8 100644
--- a/frappe/www/404.html
+++ b/frappe/www/404.html
@@ -15,7 +15,9 @@ html, body {
}
{% include "templates/styles/card_style.css" %}
-
+
{{_("Page Missing or Moved")}}
@@ -29,4 +31,4 @@ html, body {
background-color: #f5f7fa;
}
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/frappe/www/website_script.js b/frappe/www/website_script.js
index 7fdc2e94d6..e31b6812d5 100644
--- a/frappe/www/website_script.js
+++ b/frappe/www/website_script.js
@@ -14,7 +14,7 @@ ga('send', 'pageview');
{%- endif %}
{% if enable_view_tracking %}
- if (navigator.doNotTrack != 1) {
+ if (navigator.doNotTrack != 1 && !window.is_404) {
frappe.ready(() => {
let browser = frappe.utils.get_browser();
frappe.call("frappe.website.doctype.web_page_view.web_page_view.make_view_log", {
From fb66f85d6364f26b4d1cc4281aed6ac80ee8bdb7 Mon Sep 17 00:00:00 2001
From: Shivam Mishra
Date: Tue, 5 May 2020 15:06:48 +0530
Subject: [PATCH 040/307] feat: update website analytics report
---
.../website_analytics/website_analytics.py | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/frappe/website/report/website_analytics/website_analytics.py b/frappe/website/report/website_analytics/website_analytics.py
index 8b2d5b3806..b821cbff1f 100644
--- a/frappe/website/report/website_analytics/website_analytics.py
+++ b/frappe/website/report/website_analytics/website_analytics.py
@@ -17,8 +17,8 @@ class WebsiteAnalytics(object):
def run(self):
columns = self.get_columns()
data = self.get_data()
- summary = self.get_report_summary()
chart = self.get_chart_data()
+ summary = self.get_report_summary()
return columns, data, None, chart, summary
def get_columns(self):
@@ -56,7 +56,7 @@ class WebsiteAnalytics(object):
field, date_format = _get_field_for_chart(self.filters.range)
- data = frappe.db.sql("""
+ self.chart_data = frappe.db.sql("""
SELECT
DATE_FORMAT({0}, %s) as date,
COUNT(*) as count,
@@ -65,9 +65,9 @@ class WebsiteAnalytics(object):
WHERE creation BETWEEN %s AND %s
GROUP BY DATE_FORMAT({0}, %s)
ORDER BY creation
- """.format(field), (date_format, self.filters.from_date, self.filters.to_date, date_format), as_dict=1, debug=1)
+ """.format(field), (date_format, self.filters.from_date, self.filters.to_date, date_format), as_dict=1)
- return self.prepare_chart_data(data)
+ return self.prepare_chart_data(self.chart_data)
def prepare_chart_data(self, data):
date_range = get_date_range(self.filters.from_date, self.filters.to_date, self.filters.range)
@@ -121,14 +121,12 @@ class WebsiteAnalytics(object):
def get_report_summary(self):
- summary_data = frappe.get_all("Web Page View", fields=['is_unique', 'count(*) as count'], filters=self.query_filters, group_by="is_unique")
-
total_count = 0
unique_count = 0
- for data in summary_data:
- if data.get('is_unique'):
- unique_count = data.get('count')
+ for data in self.chart_data:
+ unique_count += data.get('unique_count')
total_count += data.get('count')
+
report_summary = [
{
"value": total_count,
From 606c57be5d849335513025d6ef12e1ab50613c1b Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Tue, 5 May 2020 17:35:26 +0530
Subject: [PATCH 041/307] fix: error message
---
frappe/desk/form/assign_to.py | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/frappe/desk/form/assign_to.py b/frappe/desk/form/assign_to.py
index be83dc957e..6178690b1f 100644
--- a/frappe/desk/form/assign_to.py
+++ b/frappe/desk/form/assign_to.py
@@ -41,6 +41,9 @@ def add(args=None):
if not args:
args = frappe.local.form_dict
+ users_with_duplicate_todo = []
+ shared_with_users = []
+
for assign_to in json.loads(args.get("assign_to")):
filters = {
"reference_type": args['doctype'],
@@ -50,8 +53,7 @@ def add(args=None):
}
if frappe.get_all("ToDo", filters=filters):
- if not args.get("bulk_assign"):
- frappe.throw(_("Already in user's ToDo list"), DuplicateToDoError)
+ users_with_duplicate_todo.append(assign_to)
else:
from frappe.utils import nowdate
@@ -80,7 +82,7 @@ def add(args=None):
# if assignee does not have permissions, share
if not frappe.has_permission(doc=doc, user=assign_to):
frappe.share.add(doc.doctype, doc.name, assign_to)
- frappe.msgprint(_('Shared with user {0} with read access').format(assign_to, alert=True))
+ shared_with_users.append(assign_to)
# make this document followed by assigned user
follow_document(args['doctype'], args['name'], assign_to)
@@ -89,6 +91,14 @@ def add(args=None):
notify_assignment(d.assigned_by, d.owner, d.reference_type, d.reference_name, action='ASSIGN',
description=args.get("description"))
+ if shared_with_users:
+ user_list = format_message_for_assign_to(shared_with_users)
+ frappe.msgprint(_("Shared with the following Users with Read access:{0}").format(user_list, alert=True))
+
+ if users_with_duplicate_todo:
+ user_list = format_message_for_assign_to(users_with_duplicate_todo)
+ frappe.msgprint(_("Already in the following Users ToDo list:{0}").format(user_list, alert=True))
+
return get(args)
@frappe.whitelist()
@@ -186,3 +196,5 @@ def notify_assignment(assigned_by, owner, doc_type, doc_name, action='CLOSE',
enqueue_create_notification(owner, notification_doc)
+def format_message_for_assign_to(users):
+ return "
" + "
".join(users)
\ No newline at end of file
From f684756fba34fcd5ac1099ea7938f64fe08e574d Mon Sep 17 00:00:00 2001
From: Shivam Mishra
Date: Tue, 5 May 2020 18:22:04 +0530
Subject: [PATCH 042/307] feat: added website analytics report
---
.../website_analytics/website_analytics.js | 2 -
.../website_analytics/website_analytics.py | 116 +++++++++++++++---
2 files changed, 98 insertions(+), 20 deletions(-)
diff --git a/frappe/website/report/website_analytics/website_analytics.js b/frappe/website/report/website_analytics/website_analytics.js
index b607a16eb4..7e051afa8c 100644
--- a/frappe/website/report/website_analytics/website_analytics.js
+++ b/frappe/website/report/website_analytics/website_analytics.js
@@ -9,14 +9,12 @@ frappe.query_reports["Website Analytics"] = {
label: __("From Date"),
fieldtype: "Date",
default: frappe.datetime.add_days(frappe.datetime.now_date(true), -7),
- reqd: 1
},
{
fieldname:"to_date",
label: __("To Date"),
fieldtype: "Date",
default: frappe.datetime.now_date(true),
- reqd: 1
},
{
fieldname: "range",
diff --git a/frappe/website/report/website_analytics/website_analytics.py b/frappe/website/report/website_analytics/website_analytics.py
index b821cbff1f..694bc9e797 100644
--- a/frappe/website/report/website_analytics/website_analytics.py
+++ b/frappe/website/report/website_analytics/website_analytics.py
@@ -3,6 +3,7 @@
from __future__ import unicode_literals
import frappe
+from datetime import datetime
from frappe.utils.dateutils import get_date_range
def execute(filters=None):
@@ -11,6 +12,16 @@ def execute(filters=None):
class WebsiteAnalytics(object):
def __init__(self, filters=None):
self.filters = frappe._dict(filters or {})
+
+ if not self.filters.to_date:
+ self.filters.to_date = datetime.now()
+
+ if not self.filters.from_date:
+ self.filters.from_date = frappe.utils.add_days(self.filters.to_date, -7)
+
+ if not self.filters.range:
+ self.filters.range = "D"
+
self.filters.to_date = frappe.utils.add_days(self.filters.to_date, 1)
self.query_filters = {'creation': ['between', [self.filters.from_date, self.filters.to_date]]}
@@ -19,7 +30,8 @@ class WebsiteAnalytics(object):
data = self.get_data()
chart = self.get_chart_data()
summary = self.get_report_summary()
- return columns, data, None, chart, summary
+
+ return columns, data[:250], None, chart, summary
def get_columns(self):
return [
@@ -34,38 +46,105 @@ class WebsiteAnalytics(object):
"label": "Page Views",
"fieldtype": "Int",
"width": 150
+ },
+ {
+ "fieldname": "unique_count",
+ "label": "Unique Visitors",
+ "fieldtype": "Int",
+ "width": 150
}
]
def get_data(self):
- data = frappe.get_all("Web Page View", fields=['path', 'count(*) as count'], filters=self.query_filters, group_by="path", order_by='count desc')
+ pg_query = """
+ SELECT
+ path,
+ COUNT(*) as count,
+ COUNT(CASE WHEN CAST(is_unique as Integer) = 1 THEN 1 END) as unique_count
+ FROM `tabWeb Page View`
+ WHERE coalesce("tabWeb Page View".creation, '0001-01-01') BETWEEN %s AND %s
+ GROUP BY path
+ ORDER BY count desc
+ """
+
+ mariadb_query = """
+ SELECT
+ path,
+ COUNT(*) as count,
+ COUNT(CASE WHEN is_unique = 1 THEN 1 END) as unique_count
+ FROM `tabWeb Page View`
+ WHERE creation BETWEEN %s AND %s
+ GROUP BY path
+ ORDER BY count desc
+ """
+
+ data = frappe.db.multisql({
+ "mariadb": mariadb_query,
+ "postgres": pg_query
+ }, (self.filters.from_date, self.filters.to_date))
return data
- def get_chart_data(self):
- def _get_field_for_chart(filters_range):
- field = 'creation'
- date_format = '%Y-%m-%d'
+ def _get_query_for_mariadb(self):
+ filters_range = self.filters.range
+ field = 'creation'
+ date_format = '%Y-%m-%d'
- if filters_range == "W":
- field = 'ADDDATE(creation, INTERVAL 1-DAYOFWEEK(creation) DAY)'
+ if filters_range == "W":
+ field = 'ADDDATE(creation, INTERVAL 1-DAYOFWEEK(creation) DAY)'
- elif filters_range == "M":
- date_format = '%Y-%m-01'
+ elif filters_range == "M":
+ date_format = '%Y-%m-01'
- return field, date_format
-
- field, date_format = _get_field_for_chart(self.filters.range)
-
- self.chart_data = frappe.db.sql("""
+ query = """
SELECT
DATE_FORMAT({0}, %s) as date,
COUNT(*) as count,
- count(CASE WHEN is_unique = 1 THEN 1 END) as unique_count
+ COUNT(CASE WHEN is_unique = 1 THEN 1 END) as unique_count
FROM `tabWeb Page View`
WHERE creation BETWEEN %s AND %s
GROUP BY DATE_FORMAT({0}, %s)
ORDER BY creation
- """.format(field), (date_format, self.filters.from_date, self.filters.to_date, date_format), as_dict=1)
+ """.format(field)
+
+ values = (date_format, self.filters.from_date, self.filters.to_date, date_format)
+
+ return query, values
+
+ def _get_query_for_postgres(self):
+ filters_range = self.filters.range
+ field = 'creation'
+ granularity = 'day'
+
+ if filters_range == "W":
+ granularity = 'week'
+
+ elif filters_range == "M":
+ granularity = 'day'
+
+ query = """
+ SELECT
+ DATE_TRUNC(%s, {0}) as date,
+ COUNT(*) as count,
+ COUNT(CASE WHEN CAST(is_unique as Integer) = 1 THEN 1 END) as unique_count
+ FROM "tabWeb Page View"
+ WHERE coalesce("tabWeb Page View".{0}, '0001-01-01') BETWEEN %s AND %s
+ GROUP BY date_trunc(%s, {0})
+ ORDER BY date
+ """.format(field)
+
+ values = (granularity, self.filters.from_date, self.filters.to_date, granularity)
+
+ return query, values
+
+ def get_chart_data(self):
+ current_dialect = frappe.db.db_type or 'mariadb'
+
+ if current_dialect == 'mariadb':
+ query, values = self._get_query_for_mariadb()
+ else:
+ query, values = self._get_query_for_postgres()
+
+ self.chart_data = frappe.db.sql(query, values=values, as_dict=1)
return self.prepare_chart_data(self.chart_data)
@@ -114,7 +193,8 @@ class WebsiteAnalytics(object):
},
'axisOptions': {
'xIsSeries': 1
- }
+ },
+ 'colors': ['#7cd6fd', '#5e64ff']
}
return chart
From 83380f25475edfb3bec8d79cad7013d78443b9b4 Mon Sep 17 00:00:00 2001
From: Shivam Mishra
Date: Tue, 5 May 2020 18:22:47 +0530
Subject: [PATCH 043/307] feat: added website analytics chart as JSON fixture
---
frappe/model/sync.py | 5 ++--
.../website_analytics/website_analytics.json | 24 +++++++++++++++++++
2 files changed, 27 insertions(+), 2 deletions(-)
create mode 100644 frappe/website/dashboard_chart/website_analytics/website_analytics.json
diff --git a/frappe/model/sync.py b/frappe/model/sync.py
index c2acb59f63..3dba994134 100644
--- a/frappe/model/sync.py
+++ b/frappe/model/sync.py
@@ -52,7 +52,8 @@ def sync_for(app_name, force=0, sync_everything = False, verbose=False, reset_pe
("desk", "desk_card"),
("desk", "desk_chart"),
("desk", "desk_shortcut"),
- ("desk", "desk_page")):
+ ("desk", "desk_page"),
+ ("desk", "dashboard_chart")):
files.append(os.path.join(frappe.get_app_path("frappe"), d[0],
"doctype", d[1], d[1] + ".json"))
@@ -82,7 +83,7 @@ def get_doc_files(files, start_path, force=0, sync_everything = False, verbose=F
document_types = ['doctype', 'page', 'report', 'dashboard_chart_source', 'print_format',
'website_theme', 'web_form', 'web_template', 'notification', 'print_style',
'data_migration_mapping', 'data_migration_plan', 'desk_page',
- 'onboarding_step', 'onboarding']
+ 'onboarding_step', 'onboarding', 'dashboard_chart']
for doctype in document_types:
doctype_path = os.path.join(start_path, doctype)
diff --git a/frappe/website/dashboard_chart/website_analytics/website_analytics.json b/frappe/website/dashboard_chart/website_analytics/website_analytics.json
new file mode 100644
index 0000000000..eeeb1a11f9
--- /dev/null
+++ b/frappe/website/dashboard_chart/website_analytics/website_analytics.json
@@ -0,0 +1,24 @@
+{
+ "chart_name": "Website Analytics",
+ "chart_type": "Report",
+ "creation": "2020-05-05 18:14:19.369181",
+ "custom_options": "{\"type\": \"line\", \"lineOptions\": {\"regionFill\": 1}, \"axisOptions\": {\"shortenYAxisNumbers\": 1}, \"colors\": [\"#7cd6fd\", \"#5e64ff\"], \"tooltipOptions\": {}}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "filters_json": "{}",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_custom": 1,
+ "is_public": 1,
+ "modified": "2020-05-05 18:16:47.383649",
+ "modified_by": "Administrator",
+ "name": "Website Analytics",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Website Analytics",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Line",
+ "y_axis": []
+}
\ No newline at end of file
From 06e4e6a3b933b28e29bcd7e01bf1027939a236a1 Mon Sep 17 00:00:00 2001
From: Shivam Mishra
Date: Tue, 5 May 2020 18:29:42 +0530
Subject: [PATCH 044/307] feat: add analytics chart to desk
---
frappe/website/desk_page/website/website.json | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/frappe/website/desk_page/website/website.json b/frappe/website/desk_page/website/website.json
index 1c6066d21e..c42a17d404 100644
--- a/frappe/website/desk_page/website/website.json
+++ b/frappe/website/desk_page/website/website.json
@@ -27,7 +27,11 @@
}
],
"category": "Modules",
- "charts": [],
+ "charts": [
+ {
+ "chart_name": "Website Analytics"
+ }
+ ],
"creation": "2020-03-02 14:13:51.089373",
"developer_mode_only": 0,
"disable_user_customization": 0,
@@ -37,7 +41,7 @@
"idx": 0,
"is_standard": 1,
"label": "Website",
- "modified": "2020-04-26 13:03:49.094728",
+ "modified": "2020-05-05 18:17:13.232473",
"modified_by": "Administrator",
"module": "Website",
"name": "Website",
From e71b14c17dc9bf6b5ba7f22f8ed2899fa175e5f6 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Tue, 5 May 2020 19:53:50 +0530
Subject: [PATCH 045/307] fix: Schedule Date for Daily and Weekly frequency
---
frappe/automation/doctype/auto_repeat/auto_repeat.py | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/frappe/automation/doctype/auto_repeat/auto_repeat.py b/frappe/automation/doctype/auto_repeat/auto_repeat.py
index bfcaf684d6..c447c55727 100644
--- a/frappe/automation/doctype/auto_repeat/auto_repeat.py
+++ b/frappe/automation/doctype/auto_repeat/auto_repeat.py
@@ -299,17 +299,20 @@ def get_next_schedule_date(schedule_date, frequency, start_date, repeat_on_day=N
next_date = get_next_date(start_date, month_count)
else:
days = 7 if frequency == 'Weekly' else 1
- next_date = add_days(start_date, days)
+ next_date = add_days(schedule_date, days)
# next schedule date should be after or on current date
if not for_full_schedule:
while getdate(next_date) < getdate(today()):
if month_count:
month_count += month_map.get(frequency)
- next_date = get_next_date(start_date, month_count, day_count)
+ next_date = get_next_date(start_date, month_count, day_count)
+ elif days:
+ next_date = add_days(next_date, days)
return next_date
+
def get_next_date(dt, mcount, day=None):
dt = getdate(dt)
dt += relativedelta(months=mcount, day=day)
From 6ea8881b29106edf45155b9ac565d95f9672ded2 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 6 May 2020 12:48:15 +0530
Subject: [PATCH 046/307] fix: remove exact phrase search
---
frappe/utils/global_search.py | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/frappe/utils/global_search.py b/frappe/utils/global_search.py
index 3c4b9583f8..0272ae16f4 100644
--- a/frappe/utils/global_search.py
+++ b/frappe/utils/global_search.py
@@ -81,10 +81,10 @@ def rebuild_for_doctype(doctype):
return filters
meta = frappe.get_meta(doctype)
-
+
if cint(meta.issingle) == 1:
return
-
+
if cint(meta.istable) == 1:
parent_doctypes = frappe.get_all("DocField", fields="parent", filters={
"fieldtype": ["in", frappe.model.table_fields],
@@ -506,15 +506,13 @@ def web_search(text, scope=None, start=0, limit=20):
mariadb_conditions = postgres_conditions = ' '.join([published_condition, scope_condition])
# https://mariadb.com/kb/en/library/full-text-index-overview/#in-boolean-mode
- text = '"{}"'.format(text)
- mariadb_conditions += 'MATCH(`content`) AGAINST (%(text)s IN BOOLEAN MODE)'
- postgres_conditions += 'TO_TSVECTOR("content") @@ PLAINTO_TSQUERY(%(text)s)'
+ mariadb_conditions += 'MATCH(`content`) AGAINST ({} IN BOOLEAN MODE)'.format(frappe.db.escape('+' + text + '*'))
+ postgres_conditions += 'TO_TSVECTOR("content") @@ PLAINTO_TSQUERY({})'.format(frappe.db.escape(text))
values = {
"scope": "".join([scope, "%"]) if scope else '',
"limit": limit,
- "start": start,
- "text": text
+ "start": start
}
result = frappe.db.multisql({
From e91050b0e496d872d08a7898fb2124b3a64424ef Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 6 May 2020 13:14:22 +0530
Subject: [PATCH 047/307] fix: add admin to email unsubscribe
---
frappe/desk/page/setup_wizard/install_fixtures.py | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/frappe/desk/page/setup_wizard/install_fixtures.py b/frappe/desk/page/setup_wizard/install_fixtures.py
index c857bd077f..b74153f1c7 100644
--- a/frappe/desk/page/setup_wizard/install_fixtures.py
+++ b/frappe/desk/page/setup_wizard/install_fixtures.py
@@ -12,6 +12,7 @@ def install():
update_salutations()
update_global_search_doctypes()
setup_email_linking()
+ add_unsubscribe()
@frappe.whitelist()
def update_genders():
@@ -35,4 +36,12 @@ def setup_email_linking():
"email_id": "email_linking@example.com",
})
doc.insert(ignore_permissions=True, ignore_if_duplicate=True)
-
\ No newline at end of file
+
+def add_unsubscribe():
+ email_unsubscribe = [
+ {"email": "admin@example.com", "global_unsubscribe": 1},
+ {"email": "guest@example.com", "global_unsubscribe": 1}
+ ]
+
+ for unsubscribe in email_unsubscribe:
+ frappe.get_doc(unsubscribe).insert()
\ No newline at end of file
From 37e81e33a52da50ff16ed3e476afe97124a75000 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 6 May 2020 13:20:59 +0530
Subject: [PATCH 048/307] fix: add patch
---
frappe/desk/page/setup_wizard/install_fixtures.py | 5 ++++-
frappe/patches.txt | 1 +
frappe/patches/v13_0/email_unsubscribe.py | 13 +++++++++++++
3 files changed, 18 insertions(+), 1 deletion(-)
create mode 100644 frappe/patches/v13_0/email_unsubscribe.py
diff --git a/frappe/desk/page/setup_wizard/install_fixtures.py b/frappe/desk/page/setup_wizard/install_fixtures.py
index b74153f1c7..692c1a117a 100644
--- a/frappe/desk/page/setup_wizard/install_fixtures.py
+++ b/frappe/desk/page/setup_wizard/install_fixtures.py
@@ -44,4 +44,7 @@ def add_unsubscribe():
]
for unsubscribe in email_unsubscribe:
- frappe.get_doc(unsubscribe).insert()
\ No newline at end of file
+ if not frappe.get_all("Email Unsubscribe", filters=unsubscribe):
+ doc = frappe.new_doc("Email Unsubscribe")
+ doc.update(unsubscribe)
+ doc.insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/frappe/patches.txt b/frappe/patches.txt
index cbda8cf677..5d45cbec66 100644
--- a/frappe/patches.txt
+++ b/frappe/patches.txt
@@ -273,3 +273,4 @@ execute:frappe.delete_doc_if_exists('DocType', 'GCalendar Settings')
frappe.patches.v12_0.remove_parent_and_parenttype_from_print_formats
execute:from frappe.desk.page.setup_wizard.install_fixtures import update_genders;update_genders()
frappe.patches.v13_0.website_theme_custom_scss
+frappe.patches.v13_0.email_unsubscribe
diff --git a/frappe/patches/v13_0/email_unsubscribe.py b/frappe/patches/v13_0/email_unsubscribe.py
new file mode 100644
index 0000000000..69ed1be948
--- /dev/null
+++ b/frappe/patches/v13_0/email_unsubscribe.py
@@ -0,0 +1,13 @@
+import frappe
+
+def execute():
+ email_unsubscribe = [
+ {"email": "admin@example.com", "global_unsubscribe": 1},
+ {"email": "guest@example.com", "global_unsubscribe": 1}
+ ]
+
+ for unsubscribe in email_unsubscribe:
+ if not frappe.get_all("Email Unsubscribe", filters=unsubscribe):
+ doc = frappe.new_doc("Email Unsubscribe")
+ doc.update(unsubscribe)
+ doc.insert(ignore_permissions=True)
\ No newline at end of file
From 8383b9fc3ac18485d2379b12a0b2d97f34c96f37 Mon Sep 17 00:00:00 2001
From: "Chinmay D. Pai"
Date: Wed, 6 May 2020 14:21:44 +0530
Subject: [PATCH 049/307] fix: clear_sessions should by default include mobile
whenever password was changed, the system only logged out user for the
current device type; which is incorrect.
suppose if the user logs in through mobile and selects "logout all devices"
on password reset on desktop, the system would log the user out of all
desktop instances, leaving the mobile instance active.
Signed-off-by: Chinmay D. Pai
---
frappe/sessions.py | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/frappe/sessions.py b/frappe/sessions.py
index cca40cbc55..d317d6caf3 100644
--- a/frappe/sessions.py
+++ b/frappe/sessions.py
@@ -33,7 +33,7 @@ def clear_sessions(user=None, keep_current=False, device=None, force=False):
:param user: user name (default: current user)
:param keep_current: keep current session (default: false)
- :param device: delete sessions of this device (default: desktop)
+ :param device: delete sessions of this device (default: desktop, mobile)
:param force: triggered by the user (default false)
'''
@@ -49,13 +49,16 @@ def get_sessions_to_clear(user=None, keep_current=False, device=None):
:param user: user name (default: current user)
:param keep_current: keep current session (default: false)
- :param device: delete sessions of this device (default: desktop)
+ :param device: delete sessions of this device (default: desktop, mobile)
'''
if not user:
user = frappe.session.user
if not device:
- device = frappe.session.data.device or "desktop"
+ device = ("desktop", "mobile")
+
+ if not isinstance(device, (tuple, list)):
+ device = (device,)
offset = 0
if user == frappe.session.user:
@@ -68,12 +71,12 @@ def get_sessions_to_clear(user=None, keep_current=False, device=None):
return frappe.db.sql_list("""
SELECT `sid` FROM `tabSessions`
- WHERE user=%s
- AND device=%s
+ WHERE user=%(user)s
+ AND device in %(device)s
{condition}
ORDER BY `lastupdate` DESC
LIMIT 100 OFFSET {offset}""".format(condition=condition, offset=offset),
- (user, device))
+ {"user": user, "device": device})
def delete_session(sid=None, user=None, reason="Session Expired"):
from frappe.core.doctype.activity_log.feed import logout_feed
From 04a59352f7ccaf66758632e15415395844246280 Mon Sep 17 00:00:00 2001
From: Himanshu Warekar
Date: Wed, 6 May 2020 17:40:50 +0530
Subject: [PATCH 050/307] fix: test cases
---
frappe/desk/form/assign_to.py | 2 +-
frappe/public/js/frappe/form/sidebar/assign_to.js | 2 +-
frappe/tests/test_assign.py | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/frappe/desk/form/assign_to.py b/frappe/desk/form/assign_to.py
index 6178690b1f..6c8cd5dfbd 100644
--- a/frappe/desk/form/assign_to.py
+++ b/frappe/desk/form/assign_to.py
@@ -44,7 +44,7 @@ def add(args=None):
users_with_duplicate_todo = []
shared_with_users = []
- for assign_to in json.loads(args.get("assign_to")):
+ for assign_to in frappe.parse_json(args.get("assign_to")):
filters = {
"reference_type": args['doctype'],
"reference_name": args['name'],
diff --git a/frappe/public/js/frappe/form/sidebar/assign_to.js b/frappe/public/js/frappe/form/sidebar/assign_to.js
index 84fde564c0..95ceb246e6 100644
--- a/frappe/public/js/frappe/form/sidebar/assign_to.js
+++ b/frappe/public/js/frappe/form/sidebar/assign_to.js
@@ -130,7 +130,7 @@ frappe.ui.form.AssignToDialog = Class.extend({
this.set_description_from_doc();
},
make: function() {
- let me = this
+ let me = this;
me.dialog = new frappe.ui.Dialog({
title: __('Add to ToDo'),
diff --git a/frappe/tests/test_assign.py b/frappe/tests/test_assign.py
index f32e3c9272..439e1546c0 100644
--- a/frappe/tests/test_assign.py
+++ b/frappe/tests/test_assign.py
@@ -60,7 +60,7 @@ class TestAssign(unittest.TestCase):
def assign(doc, user):
return frappe.desk.form.assign_to.add({
- "assign_to": user,
+ "assign_to": [user],
"doctype": doc.doctype,
"name": doc.name,
"description": 'test',
From 2c12af23191518a625b77c7cf6e715826b709db8 Mon Sep 17 00:00:00 2001
From: prssanna
Date: Thu, 7 May 2020 12:12:04 +0530
Subject: [PATCH 051/307] fix: consider permissions for charts and cards
---
frappe/desk/doctype/dashboard_chart/dashboard_chart.py | 4 ++--
frappe/desk/doctype/number_card/number_card.py | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py
index 7ddb3d98f0..c03f6f8156 100644
--- a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py
+++ b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py
@@ -144,7 +144,7 @@ def get_chart_config(chart, filters, timespan, timegrain, from_date, to_date):
filters.append([doctype, datefield, '>=', from_date, False])
filters.append([doctype, datefield, '<=', to_date, False])
- data = frappe.db.get_all(
+ data = frappe.db.get_list(
doctype,
fields = [
'extract(year from `tab{doctype}`.{datefield}) as _year'.format(doctype=doctype, datefield=datefield),
@@ -182,7 +182,7 @@ def get_group_by_chart_config(chart, filters):
group_by_field = chart.group_by_based_on
doctype = chart.document_type
- data = frappe.db.get_all(
+ data = frappe.db.get_list(
doctype,
fields = [
'{} as name'.format(group_by_field),
diff --git a/frappe/desk/doctype/number_card/number_card.py b/frappe/desk/doctype/number_card/number_card.py
index 2c5655beda..2c072f44c4 100644
--- a/frappe/desk/doctype/number_card/number_card.py
+++ b/frappe/desk/doctype/number_card/number_card.py
@@ -65,7 +65,7 @@ def get_result(doc, to_date=None):
if to_date:
filters.append([doc.document_type, 'creation', '<', to_date, False])
- res = frappe.db.get_all(doc.document_type, fields=fields, filters=filters)
+ res = frappe.db.get_list(doc.document_type, fields=fields, filters=filters)
number = res[0]['result'] if res else 0
return cint(number)
From fff07548fd0e05b5e4232cbda25237a5137ff012 Mon Sep 17 00:00:00 2001
From: prssanna
Date: Thu, 7 May 2020 14:00:32 +0530
Subject: [PATCH 052/307] fix: show restricted button to indicate permission
restrictions
---
frappe/core/page/dashboard/dashboard.css | 5 +++++
frappe/core/page/dashboard/dashboard.js | 7 +++++++
frappe/public/js/frappe/list/list_view.js | 2 +-
.../frappe/views/dashboard/dashboard_view.js | 8 +++++++-
frappe/public/less/dashboard_view.less | 12 ++++++++++++
frappe/public/less/desk.less | 17 +++++++++++++++++
frappe/public/less/list.less | 18 +-----------------
7 files changed, 50 insertions(+), 19 deletions(-)
diff --git a/frappe/core/page/dashboard/dashboard.css b/frappe/core/page/dashboard/dashboard.css
index e69de29bb2..e1687a0675 100644
--- a/frappe/core/page/dashboard/dashboard.css
+++ b/frappe/core/page/dashboard/dashboard.css
@@ -0,0 +1,5 @@
+.restricted-button {
+ cursor: default;
+ position: relative;
+ right: -5px;
+}
\ No newline at end of file
diff --git a/frappe/core/page/dashboard/dashboard.js b/frappe/core/page/dashboard/dashboard.js
index 222a31a863..0634d6518c 100644
--- a/frappe/core/page/dashboard/dashboard.js
+++ b/frappe/core/page/dashboard/dashboard.js
@@ -26,6 +26,13 @@ class Dashboard {
`).appendTo(this.wrapper.find(".page-content").empty());
this.container = this.wrapper.find(".dashboard-graph");
this.page = wrapper.page;
+
+ this.page.set_title_sub(
+ $(`
`)
+ )
}
show() {
diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js
index af9a3c0221..dd9362d664 100644
--- a/frappe/public/js/frappe/list/list_view.js
+++ b/frappe/public/js/frappe/list/list_view.js
@@ -139,7 +139,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList {
show_restricted_list_indicator_if_applicable() {
const match_rules_list = frappe.perm.get_match_rules(this.doctype);
if (match_rules_list.length) {
- this.restricted_list = $(`
`)
+ this.restricted_list = $(`
`)
.prepend('
')
.click(() => this.show_restrictions(match_rules_list))
.appendTo(this.page.page_form);
diff --git a/frappe/public/js/frappe/views/dashboard/dashboard_view.js b/frappe/public/js/frappe/views/dashboard/dashboard_view.js
index 13c44d2130..83f45da5be 100644
--- a/frappe/public/js/frappe/views/dashboard/dashboard_view.js
+++ b/frappe/public/js/frappe/views/dashboard/dashboard_view.js
@@ -41,7 +41,13 @@ frappe.views.DashboardView = class DashboardView extends frappe.views.ListView {
this.$dashboard_page = this.$page.find('.layout-main-section-wrapper').addClass('dashboard-page');
this.$page.find('.page-form').empty().html(
`