From cdcfe844cbe4a6647433a3b31c53d5af99deb795 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Thu, 5 Nov 2020 12:32:51 +0530
Subject: [PATCH 01/10] feat: Init unified desk [WIP]
---
frappe/boot.py | 15 ++++
frappe/core/doctype/role/role.json | 86 ++++++++++++++++++-
frappe/public/js/frappe/ui/toolbar/toolbar.js | 16 ++--
3 files changed, 110 insertions(+), 7 deletions(-)
diff --git a/frappe/boot.py b/frappe/boot.py
index a513fed53b..6293b5b6f5 100644
--- a/frappe/boot.py
+++ b/frappe/boot.py
@@ -88,6 +88,7 @@ def get_bootinfo():
bootinfo.frequently_visited_links = frequently_visited_links()
bootinfo.link_preview_doctypes = get_link_preview_doctypes()
bootinfo.additional_filters_config = get_additional_filters_from_hooks()
+ bootinfo.desk_settings = get_desk_settings()
return bootinfo
@@ -308,3 +309,17 @@ def get_additional_filters_from_hooks():
return filter_config
+def get_desk_settings():
+ role_list = frappe.get_all('Role', fields=['*'], filters=dict(
+ name=['in', frappe.get_roles()]
+ ))
+ desk_settings = {}
+
+ desk_properties = ("search_bar", "notification", "chat", "list_sidebar",
+ "bulk_actions", "view_switcher", "form_sidebar", "timeline", "dashboard")
+
+ for role in role_list:
+ for key in desk_properties:
+ desk_settings[key] = desk_settings[key] or role[key]
+
+ return desk_settings
\ No newline at end of file
diff --git a/frappe/core/doctype/role/role.json b/frappe/core/doctype/role/role.json
index 0ad15ba10b..92f8edd12c 100644
--- a/frappe/core/doctype/role/role.json
+++ b/frappe/core/doctype/role/role.json
@@ -13,7 +13,19 @@
"column_break_4",
"disabled",
"desk_access",
- "two_factor_auth"
+ "two_factor_auth",
+ "navigation_settings_section",
+ "search_bar",
+ "notification",
+ "chat",
+ "list_settings_section",
+ "list_sidebar",
+ "bulk_actions",
+ "view_switcher",
+ "form_settings_section",
+ "form_sidebar",
+ "timeline",
+ "dashboard"
],
"fields": [
{
@@ -60,12 +72,82 @@
{
"fieldname": "column_break_4",
"fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "navigation_settings_section",
+ "fieldtype": "Section Break",
+ "label": "Navigation Settings"
+ },
+ {
+ "default": "0",
+ "fieldname": "search_bar",
+ "fieldtype": "Check",
+ "label": "Search Bar"
+ },
+ {
+ "default": "0",
+ "fieldname": "notification",
+ "fieldtype": "Check",
+ "label": "Notification"
+ },
+ {
+ "default": "1",
+ "fieldname": "chat",
+ "fieldtype": "Check",
+ "label": "Chat"
+ },
+ {
+ "fieldname": "list_settings_section",
+ "fieldtype": "Section Break",
+ "label": "List Settings"
+ },
+ {
+ "default": "0",
+ "fieldname": "list_sidebar",
+ "fieldtype": "Check",
+ "label": "Sidebar"
+ },
+ {
+ "default": "0",
+ "fieldname": "bulk_actions",
+ "fieldtype": "Check",
+ "label": "Bulk Actions"
+ },
+ {
+ "fieldname": "form_settings_section",
+ "fieldtype": "Section Break",
+ "label": "Form Settings"
+ },
+ {
+ "default": "0",
+ "fieldname": "form_sidebar",
+ "fieldtype": "Check",
+ "label": "Sidebar"
+ },
+ {
+ "default": "0",
+ "fieldname": "timeline",
+ "fieldtype": "Check",
+ "label": "Timeline"
+ },
+ {
+ "default": "0",
+ "fieldname": "dashboard",
+ "fieldtype": "Check",
+ "label": "Dashboard"
+ },
+ {
+ "default": "0",
+ "fieldname": "view_switcher",
+ "fieldtype": "Check",
+ "label": "View Switcher"
}
],
"icon": "fa fa-bookmark",
"idx": 1,
+ "index_web_pages_for_search": 1,
"links": [],
- "modified": "2020-08-06 15:42:59.036960",
+ "modified": "2020-11-05 01:25:10.536546",
"modified_by": "Administrator",
"module": "Core",
"name": "Role",
diff --git a/frappe/public/js/frappe/ui/toolbar/toolbar.js b/frappe/public/js/frappe/ui/toolbar/toolbar.js
index 8ff79aad8b..83b83003b0 100644
--- a/frappe/public/js/frappe/ui/toolbar/toolbar.js
+++ b/frappe/public/js/frappe/ui/toolbar/toolbar.js
@@ -12,10 +12,7 @@ frappe.ui.toolbar.Toolbar = class {
}));
$('.dropdown-toggle').dropdown();
- let awesome_bar = new frappe.search.AwesomeBar();
- awesome_bar.setup("#navbar-search");
- // awesome_bar.setup("#modal-search");
-
+ this.setup_awesomebar();
this.setup_notifications();
this.make();
}
@@ -157,8 +154,17 @@ frappe.ui.toolbar.Toolbar = class {
}
}
+ setup_awesomebar() {
+ if (frappe.boot.desk_settings.search_bar) {
+ let awesome_bar = new frappe.search.AwesomeBar();
+ awesome_bar.setup("#navbar-search");
+ }
+ }
+
setup_notifications () {
- this.notifications = new frappe.ui.Notifications();
+ if (frappe.boot.desk_settings.notifications) {
+ this.notifications = new frappe.ui.Notifications();
+ }
}
}
From f1d7e2a212290f281f93fd37e8380be44320450b Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Thu, 5 Nov 2020 12:33:54 +0530
Subject: [PATCH 02/10] feat: Open List or Form in new window
---
frappe/core/doctype/doctype/doctype.js | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/frappe/core/doctype/doctype/doctype.js b/frappe/core/doctype/doctype/doctype.js
index b3469abf29..e236464b95 100644
--- a/frappe/core/doctype/doctype/doctype.js
+++ b/frappe/core/doctype/doctype/doctype.js
@@ -24,11 +24,12 @@ frappe.ui.form.on('DocType', {
if (!frm.is_new() && !frm.doc.istable) {
if (frm.doc.issingle) {
frm.add_custom_button(__('Go to {0}', [frm.doc.name]), () => {
- frappe.set_route('Form', frm.doc.name);
+ window.open(`/desk#Form/${frm.doc.name}`);
+ // frappe.set_route('Form', frm.doc.name);
});
} else {
frm.add_custom_button(__('Go to {0} List', [frm.doc.name]), () => {
- frappe.set_route('List', frm.doc.name, 'List');
+ window.open(`/desk#List/${frm.doc.name}/List`);
});
}
}
From f608fc95164491e7e5efec90f64df7ab29a60886 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Wed, 11 Nov 2020 08:50:54 +0530
Subject: [PATCH 03/10] feat: Enable desk for Website User
---
frappe/auth.py | 14 ++++----------
frappe/boot.py | 4 ++--
frappe/core/doctype/user/user.py | 21 +++++++++------------
frappe/www/desk.py | 4 ++--
4 files changed, 17 insertions(+), 26 deletions(-)
diff --git a/frappe/auth.py b/frappe/auth.py
index 6d51629c58..3b18c8adb9 100644
--- a/frappe/auth.py
+++ b/frappe/auth.py
@@ -164,16 +164,10 @@ class LoginManager:
self.full_name = " ".join(filter(None, [self.info.first_name,
self.info.last_name]))
- if self.info.user_type=="Website User":
- frappe.local.cookie_manager.set_cookie("system_user", "no")
- if not resume:
- frappe.local.response["message"] = "No App"
- frappe.local.response["home_page"] = '/' + get_home_page()
- else:
- frappe.local.cookie_manager.set_cookie("system_user", "yes")
- if not resume:
- frappe.local.response['message'] = 'Logged In'
- frappe.local.response["home_page"] = "/desk"
+ frappe.local.cookie_manager.set_cookie("system_user", "yes")
+ if not resume:
+ frappe.local.response['message'] = 'Logged In'
+ frappe.local.response["home_page"] = "/desk"
if not resume:
frappe.response["full_name"] = self.full_name
diff --git a/frappe/boot.py b/frappe/boot.py
index 6293b5b6f5..bb1cff40f9 100644
--- a/frappe/boot.py
+++ b/frappe/boot.py
@@ -226,7 +226,7 @@ def load_translations(bootinfo):
def get_user_info():
user_info = frappe.db.get_all('User', fields=['`name`', 'full_name as fullname', 'user_image as image',
'gender', 'email', 'username', 'bio', 'location', 'interest', 'banner_image', 'allowed_in_mentions'],
- filters=dict(enabled=1, user_type=['!=', 'Website User']))
+ filters=dict(enabled=1))
user_info_map = {d.name: d for d in user_info}
@@ -320,6 +320,6 @@ def get_desk_settings():
for role in role_list:
for key in desk_properties:
- desk_settings[key] = desk_settings[key] or role[key]
+ desk_settings[key] = desk_settings.get(key) or role.get(key)
return desk_settings
\ No newline at end of file
diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py
index 16f4986c35..9fc6658f29 100644
--- a/frappe/core/doctype/user/user.py
+++ b/frappe/core/doctype/user/user.py
@@ -182,20 +182,17 @@ class User(Document):
def share_with_self(self):
- if self.user_type=="System User":
- frappe.share.add(self.doctype, self.name, self.name, write=1, share=1,
- flags={"ignore_share_permission": True})
- else:
- frappe.share.remove(self.doctype, self.name, self.name,
- flags={"ignore_share_permission": True, "ignore_permissions": True})
+ frappe.share.add(self.doctype, self.name, self.name, write=1, share=1,
+ flags={"ignore_share_permission": True})
def validate_share(self, docshare):
- if docshare.user == self.name:
- if self.user_type=="System User":
- if docshare.share != 1:
- frappe.throw(_("Sorry! User should have complete access to their own record."))
- else:
- frappe.throw(_("Sorry! Sharing with Website User is prohibited."))
+ pass
+ # if docshare.user == self.name:
+ # if self.user_type=="System User":
+ # if docshare.share != 1:
+ # frappe.throw(_("Sorry! User should have complete access to their own record."))
+ # else:
+ # frappe.throw(_("Sorry! Sharing with Website User is prohibited."))
def send_password_notification(self, new_password):
try:
diff --git a/frappe/www/desk.py b/frappe/www/desk.py
index b3974df852..764235f583 100644
--- a/frappe/www/desk.py
+++ b/frappe/www/desk.py
@@ -14,8 +14,8 @@ import frappe.sessions
def get_context(context):
if frappe.session.user == "Guest":
frappe.throw(_("Log in to access this page."), frappe.PermissionError)
- elif frappe.db.get_value("User", frappe.session.user, "user_type") == "Website User":
- frappe.throw(_("You are not permitted to access this page."), frappe.PermissionError)
+ # elif frappe.db.get_value("User", frappe.session.user, "user_type") == "Website User":
+ # frappe.throw(_("You are not permitted to access this page."), frappe.PermissionError)
hooks = frappe.get_hooks()
try:
From 243d5f788950c433993dc80fdc797aa8523d4438 Mon Sep 17 00:00:00 2001
From: Rushabh Mehta
Date: Tue, 10 Nov 2020 16:27:54 +0530
Subject: [PATCH 04/10] feat(wip): clean routes, not hashes
---
frappe/public/js/frappe/desk.js | 2 +-
frappe/public/js/frappe/form/form.js | 2 +-
frappe/public/js/frappe/router.js | 113 ++++++++++--------
frappe/public/js/frappe/ui/dialog.js | 11 ++
.../js/frappe/ui/toolbar/awesome_bar.js | 6 -
frappe/public/js/frappe/views/container.js | 2 +-
6 files changed, 77 insertions(+), 59 deletions(-)
diff --git a/frappe/public/js/frappe/desk.js b/frappe/public/js/frappe/desk.js
index 0e425abf25..153beabf3d 100644
--- a/frappe/public/js/frappe/desk.js
+++ b/frappe/public/js/frappe/desk.js
@@ -75,7 +75,7 @@ frappe.Application = Class.extend({
if (frappe.boot) {
if (localStorage.getItem("session_last_route")) {
- window.location.hash = localStorage.getItem("session_last_route");
+ frappe.set_route(localStorage.getItem("session_last_route"));
localStorage.removeItem("session_last_route");
}
diff --git a/frappe/public/js/frappe/form/form.js b/frappe/public/js/frappe/form/form.js
index 27de748c95..837fa09b1f 100644
--- a/frappe/public/js/frappe/form/form.js
+++ b/frappe/public/js/frappe/form/form.js
@@ -1007,7 +1007,7 @@ frappe.ui.form.Form = class FrappeForm {
return;
}
- frappe.re_route[window.location.hash] = '#Form/' + encodeURIComponent(this.doctype) + '/' + encodeURIComponent(name);
+ frappe.re_route[frappe.get_sub_path()] = 'Form/' + encodeURIComponent(this.doctype) + '/' + encodeURIComponent(name);
frappe.set_route('Form', this.doctype, name);
}
diff --git a/frappe/public/js/frappe/router.js b/frappe/public/js/frappe/router.js
index 3c729f4af2..a4315ec359 100644
--- a/frappe/public/js/frappe/router.js
+++ b/frappe/public/js/frappe/router.js
@@ -13,39 +13,59 @@ frappe.view_factory = {};
frappe.view_factories = [];
frappe.route_options = null;
frappe.route_hooks = {};
+frappe._cur_route = null;
+
+$(window).on('hashchange', function() {
+ // save the title
+
+ if (window.location.hash) {
+ console.log(window.location.hash);
+ let sub_path = frappe.get_sub_path(window.location.hash);
+ window.location.hash = '';
+ frappe.push_state(sub_path);
+ }
+});
frappe.route = function() {
// Application is not yet initiated
if (!frappe.app) return;
- if(frappe.re_route[window.location.hash] !== undefined) {
+ let sub_path = frappe.get_route_str();
+
+ if (frappe.re_route[sub_path] !== undefined) {
// after saving a doc, for example,
// "New DocType 1" and the renamed "TestDocType", both exist in history
// now if we try to go back,
// it doesn't allow us to go back to the one prior to "New DocType 1"
// Hence if this check is true, instead of changing location hash,
// we just do a back to go to the doc previous to the "New DocType 1"
- var re_route_val = frappe.get_route_str(frappe.re_route[window.location.hash]);
- var cur_route_val = frappe.get_route_str(frappe._cur_route);
- if (decodeURIComponent(re_route_val) === decodeURIComponent(cur_route_val)) {
+ var re_route_val = frappe.get_route_str(frappe.re_route[sub_path]);
+ if (decodeURIComponent(re_route_val) === decodeURIComponent(sub_path)) {
window.history.back();
return;
} else {
- window.location.hash = frappe.re_route[window.location.hash];
+ frappe.set_route(re_route_val);
+ return;
}
}
- frappe._cur_route = window.location.hash;
+ frappe._cur_route = sub_path;
- var route = frappe.get_route();
+ let route = frappe.get_route();
if (route === false) {
return;
}
frappe.route_history.push(route);
- if(route[0]) {
+ // set title
+ frappe.route_titles[sub_path] = frappe._original_title || document.title;
+
+ // hide open dialog
+ frappe.ui.hide_open_dialog();
+
+ if (route[0]) {
const title_cased_route = frappe.utils.to_title_case(route[0]);
if (title_cased_route === 'Workspace') {
frappe.views.pageview.show('');
@@ -71,18 +91,17 @@ frappe.route = function() {
}
- if(frappe.route_titles[window.location.hash]) {
- frappe.utils.set_title(frappe.route_titles[window.location.hash]);
+ if (frappe.route_titles[sub_path]) {
+ frappe.utils.set_title(frappe.route_titles[sub_path]);
} else {
setTimeout(function() {
frappe.route_titles[frappe.get_route_str()] = frappe._original_title || document.title;
}, 1000);
}
- if(window.mixpanel) {
- window.mixpanel.track(route.slice(0, 2).join(' '));
- }
-}
+ frappe.route.trigger('change');
+
+};
frappe.get_route = function(route) {
// for app
@@ -91,7 +110,7 @@ frappe.get_route = function(route) {
var parts = null;
var doc_name = route[route.length - 1];
// if the last part contains ? then check if it is valid query string
- if(doc_name.indexOf("?") < doc_name.indexOf("=")){
+ if (doc_name.indexOf("?") < doc_name.indexOf("=")) {
parts = doc_name.split("?");
route[route.length - 1] = parts[0];
} else {
@@ -112,7 +131,7 @@ frappe.get_route = function(route) {
}
frappe.get_prev_route = function() {
- if(frappe.route_history && frappe.route_history.length > 1) {
+ if (frappe.route_history && frappe.route_history.length > 1) {
return frappe.route_history[frappe.route_history.length - 2];
} else {
return [];
@@ -122,7 +141,7 @@ frappe.get_prev_route = function() {
frappe._decode_str = function(r) {
try {
return decodeURIComponent(r);
- } catch(e) {
+ } catch (e) {
if (e instanceof URIError) {
return r;
} else {
@@ -132,30 +151,37 @@ frappe._decode_str = function(r) {
}
frappe.get_raw_route_str = function(route) {
- if(!route)
+ if (!route) {
route = window.location.hash;
+ }
- if(route.substr(0,1)=='#') route = route.substr(1);
- if(route.substr(0,1)=='!') route = route.substr(1);
+ if (!route && window.location.pathname.startsWith('/desk')) {
+ // route is without hash
+ route = window.location.pathname.substr(5);
+ }
+
+ if (route.substr(0, 1)=='/') route = route.substr(1);
+ if (route.substr(0, 1)=='#') route = route.substr(1);
+ if (route.substr(0, 1)=='!') route = route.substr(1);
return route;
-}
+};
-frappe.get_route_str = function(route) {
+frappe.get_sub_path = frappe.get_route_str = function(route) {
var rawRoute = frappe.get_raw_route_str(route);
route = $.map(rawRoute.split('/'), frappe._decode_str).join('/');
return route;
-}
+};
frappe.set_route = function() {
return new Promise(resolve => {
var params = arguments;
- if(params.length===1 && $.isArray(params[0])) {
+ if (params.length===1 && $.isArray(params[0])) {
params = params[0];
}
var route = $.map(params, function(a) {
- if($.isPlainObject(a)) {
+ if ($.isPlainObject(a)) {
frappe.route_options = a;
return null;
} else {
@@ -174,18 +200,28 @@ frappe.set_route = function() {
url.hash = route;
window.location.replace(url);
} else {
- window.location.hash = route;
+ //
+ // window.location.hash = route;
+
+ // routing v2
+ frappe.push_state(route);
}
// Set favicon (app.js)
frappe.provide('frappe.app');
frappe.app.set_favicon && frappe.app.set_favicon();
+
setTimeout(() => {
frappe.after_ajax && frappe.after_ajax(() => {
resolve();
});
}, 100);
});
+};
+
+frappe.push_state = function (route) {
+ history.pushState(null, null, `/desk/${route}`);
+ frappe.route();
}
frappe.set_re_route = function() {
@@ -196,29 +232,6 @@ frappe.set_re_route = function() {
frappe.has_route_options = function() {
return Boolean(Object.keys(frappe.route_options || {}).length);
-}
-
-frappe._cur_route = null;
-
-$(window).on('hashchange', function() {
- // save the title
- frappe.route_titles[frappe._cur_route] = frappe._original_title || document.title;
-
- if(window.location.hash==frappe._cur_route)
- return;
-
- // hide open dialog
- if(window.cur_dialog) {
- if (!cur_dialog.minimizable) {
- cur_dialog.hide();
- } else if (!cur_dialog.is_minimized) {
- cur_dialog.toggle_minimize();
- }
- }
-
- frappe.route();
-
- frappe.route.trigger('change');
-});
+};
frappe.utils.make_event_emitter(frappe.route);
diff --git a/frappe/public/js/frappe/ui/dialog.js b/frappe/public/js/frappe/ui/dialog.js
index c8cef56420..bbed14730b 100644
--- a/frappe/public/js/frappe/ui/dialog.js
+++ b/frappe/public/js/frappe/ui/dialog.js
@@ -229,3 +229,14 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup {
this.header.find('.modal-title').toggleClass('cursor-pointer');
}
};
+
+frappe.ui.hide_open_dialog = () => {
+ // hide open dialog
+ if (window.cur_dialog) {
+ if (!cur_dialog.minimizable) {
+ cur_dialog.hide();
+ } else if (!cur_dialog.is_minimized) {
+ cur_dialog.toggle_minimize();
+ }
+ }
+}
diff --git a/frappe/public/js/frappe/ui/toolbar/awesome_bar.js b/frappe/public/js/frappe/ui/toolbar/awesome_bar.js
index e11adcfb66..556e1fbb97 100644
--- a/frappe/public/js/frappe/ui/toolbar/awesome_bar.js
+++ b/frappe/public/js/frappe/ui/toolbar/awesome_bar.js
@@ -107,13 +107,7 @@ frappe.search.AwesomeBar = Class.extend({
if(item.onclick) {
item.onclick(item.match);
} else {
- var previous_hash = window.location.hash;
frappe.set_route(item.route);
-
- // hashchange didn't fire!
- if (window.location.hash == previous_hash) {
- frappe.route();
- }
}
$input.val("");
});
diff --git a/frappe/public/js/frappe/views/container.js b/frappe/public/js/frappe/views/container.js
index a5227b4271..ae4aaba570 100644
--- a/frappe/public/js/frappe/views/container.js
+++ b/frappe/public/js/frappe/views/container.js
@@ -82,7 +82,7 @@ frappe.views.Container = Class.extend({
$(document).trigger("page-change");
- this.page._route = window.location.hash;
+ this.page._route = frappe.get_sub_path();
$(this.page).trigger('show');
!this.page.disable_scroll_to_top && frappe.utils.scroll_to(0);
frappe.breadcrumbs.update();
From 029e757cc67b1fc5e01e7d7a1c2724029c02b1f8 Mon Sep 17 00:00:00 2001
From: Rushabh Mehta
Date: Wed, 11 Nov 2020 10:59:50 +0530
Subject: [PATCH 05/10] fix(minor): routing in various places to support v2
routing
---
frappe/hooks.py | 18 +++++----
frappe/public/js/frappe/desk.js | 29 +++++++-------
frappe/public/js/frappe/router.js | 65 ++++++++++++++++++++++---------
frappe/website/render.py | 4 ++
frappe/www/desk.html | 1 +
frappe/www/desk.py | 1 +
6 files changed, 79 insertions(+), 39 deletions(-)
diff --git a/frappe/hooks.py b/frappe/hooks.py
index 17d022465e..b3d7623e0e 100644
--- a/frappe/hooks.py
+++ b/frappe/hooks.py
@@ -29,16 +29,18 @@ page_js = {
# website
app_include_js = [
- "assets/js/libs.min.js",
- "assets/js/desk.min.js",
- "assets/js/list.min.js",
- "assets/js/form.min.js",
- "assets/js/control.min.js",
- "assets/js/report.min.js",
+ "/assets/js/libs.min.js",
+ "/assets/js/desk.min.js",
+ "/assets/js/list.min.js",
+ "/assets/js/form.min.js",
+ "/assets/js/control.min.js",
+ "/assets/js/report.min.js",
]
app_include_css = [
- "assets/css/desk.min.css",
- "assets/css/report.min.css",
+ "/assets/css/desk.min.css",
+ "/assets/css/list.min.css",
+ "/assets/css/form.min.css",
+ "/assets/css/report.min.css",
]
doctype_js = {
diff --git a/frappe/public/js/frappe/desk.js b/frappe/public/js/frappe/desk.js
index 153beabf3d..78c367c8e9 100644
--- a/frappe/public/js/frappe/desk.js
+++ b/frappe/public/js/frappe/desk.js
@@ -73,19 +73,9 @@ frappe.Application = Class.extend({
this.set_rtl();
- if (frappe.boot) {
- if (localStorage.getItem("session_last_route")) {
- frappe.set_route(localStorage.getItem("session_last_route"));
- localStorage.removeItem("session_last_route");
- }
-
- }
-
// page container
this.make_page_container();
-
- // route to home page
- frappe.route();
+ this.set_route();
// trigger app startup
$(document).trigger('startup');
@@ -155,7 +145,7 @@ frappe.Application = Class.extend({
});
}, 300000); // check every 5 minutes
- if(frappe.user.has_role("System Manager")){
+ if (frappe.user.has_role("System Manager")) {
setInterval(function() {
frappe.call({
method: 'frappe.core.doctype.log_settings.log_settings.has_unseen_error_log',
@@ -164,7 +154,7 @@ frappe.Application = Class.extend({
},
callback: function(r) {
console.log(r);
- if(r.message.show_alert){
+ if (r.message.show_alert) {
frappe.show_alert({
indicator: 'red',
message: r.message.message
@@ -179,6 +169,19 @@ frappe.Application = Class.extend({
this.fetch_tags();
},
+ set_route() {
+ if (frappe.boot && localStorage.getItem("session_last_route")) {
+ frappe.set_route(localStorage.getItem("session_last_route"));
+ localStorage.removeItem("session_last_route");
+ } else if (frappe._cur_route) {
+ // go to the appropriate sub-path
+ frappe.set_route(frappe._cur_route);
+ } else {
+ // route to home page
+ frappe.route();
+ }
+ },
+
setup_frappe_vue() {
Vue.prototype.__ = window.__;
Vue.prototype.frappe = window.frappe;
diff --git a/frappe/public/js/frappe/router.js b/frappe/public/js/frappe/router.js
index a4315ec359..78d1b7e1d1 100644
--- a/frappe/public/js/frappe/router.js
+++ b/frappe/public/js/frappe/router.js
@@ -16,22 +16,39 @@ frappe.route_hooks = {};
frappe._cur_route = null;
$(window).on('hashchange', function() {
- // save the title
-
if (window.location.hash) {
- console.log(window.location.hash);
let sub_path = frappe.get_sub_path(window.location.hash);
window.location.hash = '';
frappe.push_state(sub_path);
}
});
+// routing v2, capture all clicks so that the target is managed with push-state
+$('body').on('click', 'a', function(e) {
+ let override = (e, route) => {
+ e.preventDefault();
+ frappe.push_state(frappe.get_sub_path(route));
+ return false;
+ };
+
+ // target has "#" ,this is a v1 style route, so remake it.
+ if (e.target.hash) {
+ return override(e, e.target.hash);
+ }
+
+ // target has "/desk, this is a v2 style route.
+ if (e.target.pathname &&
+ (e.target.pathname.startWith('/desk') || e.target.pathname.startWith('desk'))) {
+ return override(e, e.target.pathname);
+ }
+});
+
frappe.route = function() {
// Application is not yet initiated
if (!frappe.app) return;
- let sub_path = frappe.get_route_str();
+ let sub_path = frappe.get_sub_path();
if (frappe.re_route[sub_path] !== undefined) {
// after saving a doc, for example,
@@ -40,7 +57,7 @@ frappe.route = function() {
// it doesn't allow us to go back to the one prior to "New DocType 1"
// Hence if this check is true, instead of changing location hash,
// we just do a back to go to the doc previous to the "New DocType 1"
- var re_route_val = frappe.get_route_str(frappe.re_route[sub_path]);
+ var re_route_val = frappe.get_sub_path(frappe.re_route[sub_path]);
if (decodeURIComponent(re_route_val) === decodeURIComponent(sub_path)) {
window.history.back();
return;
@@ -105,7 +122,7 @@ frappe.route = function() {
frappe.get_route = function(route) {
// for app
- route = frappe.get_raw_route_str(route).split('/');
+ route = frappe.get_sub_path_string(route).split('/');
route = $.map(route, frappe._decode_str);
var parts = null;
var doc_name = route[route.length - 1];
@@ -150,16 +167,19 @@ frappe._decode_str = function(r) {
}
}
-frappe.get_raw_route_str = function(route) {
+frappe.get_sub_path_string = function(route) {
+ // return clean sub_path from hash or url
+ // supports both v1 and v2 routing
+
if (!route) {
route = window.location.hash;
}
-
- if (!route && window.location.pathname.startsWith('/desk')) {
- // route is without hash
- route = window.location.pathname.substr(5);
+ if (!route) {
+ route = window.location.pathname;
}
+ if (route.substr(0, 1)=='/') route = route.substr(1);
+ if (route.startsWith('desk')) route = route.substr(4);
if (route.substr(0, 1)=='/') route = route.substr(1);
if (route.substr(0, 1)=='#') route = route.substr(1);
if (route.substr(0, 1)=='!') route = route.substr(1);
@@ -168,8 +188,8 @@ frappe.get_raw_route_str = function(route) {
};
frappe.get_sub_path = frappe.get_route_str = function(route) {
- var rawRoute = frappe.get_raw_route_str(route);
- route = $.map(rawRoute.split('/'), frappe._decode_str).join('/');
+ var sub_path = frappe.get_sub_path_string(route);
+ route = $.map(sub_path.split('/'), frappe._decode_str).join('/');
return route;
};
@@ -220,14 +240,23 @@ frappe.set_route = function() {
};
frappe.push_state = function (route) {
- history.pushState(null, null, `/desk/${route}`);
- frappe.route();
-}
+ let url = `/desk/${route}`;
+ if (window.location.pathname !== url) {
+ // cleanup any remenants of v1 routing
+ window.location.hash = '';
+
+ // push state so the browser looks fine
+ history.pushState(null, null, url);
+
+ // now process the route
+ frappe.route();
+ }
+};
frappe.set_re_route = function() {
- var tmp = window.location.hash;
+ var tmp = frappe.get_sub_path();
frappe.set_route.apply(null, arguments);
- frappe.re_route[tmp] = window.location.hash;
+ frappe.re_route[tmp] = frappe.get_sub_path();
};
frappe.has_route_options = function() {
diff --git a/frappe/website/render.py b/frappe/website/render.py
index af3b18b233..e83357f8be 100644
--- a/frappe/website/render.py
+++ b/frappe/website/render.py
@@ -252,6 +252,10 @@ def resolve_path(path):
if path != "index":
path = resolve_from_map(path)
+ if path.startswith("desk"):
+ path = "desk"
+ frappe.flags.desk_route = path[5:]
+
return path
def resolve_from_map(path):
diff --git a/frappe/www/desk.html b/frappe/www/desk.html
index c39933eb57..0f0aa0f34e 100644
--- a/frappe/www/desk.html
+++ b/frappe/www/desk.html
@@ -47,6 +47,7 @@
if(!window.frappe) window.frappe = {};
frappe.boot = {{ boot }};
+ frappe._cur_route = "{{ desk_route }}";
frappe.csrf_token = "{{ csrf_token }}";
diff --git a/frappe/www/desk.py b/frappe/www/desk.py
index 764235f583..dd0a684fae 100644
--- a/frappe/www/desk.py
+++ b/frappe/www/desk.py
@@ -37,6 +37,7 @@ def get_context(context):
boot_json = re.sub("\", "", boot_json)
context.update({
+ "desk_route": frappe.flags.desk_route or "",
"no_cache": 1,
"build_version": get_build_version(),
"include_js": hooks["app_include_js"],
From 984123c3eb67cf4de93f42e2b8571379246e2ee9 Mon Sep 17 00:00:00 2001
From: Rushabh Mehta
Date: Wed, 11 Nov 2020 11:45:15 +0530
Subject: [PATCH 06/10] fix(routing-v2): handle pop state and use currentTarget
---
frappe/public/js/frappe/router.js | 30 ++++++++++-------------
frappe/public/js/frappe/views/pageview.js | 28 ++++++++++++++++-----
2 files changed, 35 insertions(+), 23 deletions(-)
diff --git a/frappe/public/js/frappe/router.js b/frappe/public/js/frappe/router.js
index 78d1b7e1d1..637def1bc3 100644
--- a/frappe/public/js/frappe/router.js
+++ b/frappe/public/js/frappe/router.js
@@ -23,6 +23,11 @@ $(window).on('hashchange', function() {
}
});
+window.addEventListener('popstate', (event) => {
+ // forward-back button, just re-render based on current route
+ frappe.route();
+});
+
// routing v2, capture all clicks so that the target is managed with push-state
$('body').on('click', 'a', function(e) {
let override = (e, route) => {
@@ -32,14 +37,14 @@ $('body').on('click', 'a', function(e) {
};
// target has "#" ,this is a v1 style route, so remake it.
- if (e.target.hash) {
- return override(e, e.target.hash);
+ if (e.currentTarget.hash) {
+ return override(e, e.currentTarget.hash);
}
// target has "/desk, this is a v2 style route.
- if (e.target.pathname &&
- (e.target.pathname.startWith('/desk') || e.target.pathname.startWith('desk'))) {
- return override(e, e.target.pathname);
+ if (e.currentTarget.pathname &&
+ (e.currentTarget.pathname.startsWith('/desk') || e.currentTarget.pathname.startsWith('desk'))) {
+ return override(e, e.currentTarget.pathname);
}
});
@@ -70,9 +75,6 @@ frappe.route = function() {
frappe._cur_route = sub_path;
let route = frappe.get_route();
- if (route === false) {
- return;
- }
frappe.route_history.push(route);
@@ -103,7 +105,7 @@ frappe.route = function() {
}
}
} else {
- // Show desk
+ // Show home
frappe.views.pageview.show('');
}
@@ -138,12 +140,6 @@ frappe.get_route = function(route) {
frappe.route_options = $.extend(frappe.route_options || {}, query_params);
}
- // backward compatibility
- if (route && route[0]==='Module') {
- frappe.set_route('modules', route[1]);
- return false;
- }
-
return route;
}
@@ -178,8 +174,8 @@ frappe.get_sub_path_string = function(route) {
route = window.location.pathname;
}
- if (route.substr(0, 1)=='/') route = route.substr(1);
- if (route.startsWith('desk')) route = route.substr(4);
+ if (route.substr(0, 1)=='/') route = route.substr(1); // for /desk/sub
+ if (route.startsWith('desk')) route = route.substr(4); // for desk/sub
if (route.substr(0, 1)=='/') route = route.substr(1);
if (route.substr(0, 1)=='#') route = route.substr(1);
if (route.substr(0, 1)=='!') route = route.substr(1);
diff --git a/frappe/public/js/frappe/views/pageview.js b/frappe/public/js/frappe/views/pageview.js
index 90c5965b85..e2c762edd4 100644
--- a/frappe/public/js/frappe/views/pageview.js
+++ b/frappe/public/js/frappe/views/pageview.js
@@ -38,15 +38,31 @@ frappe.views.pageview = {
},
show: function(name) {
- if(!name) {
+ if (!name) {
name = (frappe.boot ? frappe.boot.home_page : window.page_name);
+
+ if (name === "workspace") {
+ if (!frappe.workspace) {
+ let page = frappe.container.add_page('workspace');
+ let container = $('').appendTo(page);
+ container = $('').appendTo(container);
+
+ frappe.workspace = new Desktop({
+ wrapper: container
+ });
+ }
+ }
+ frappe.container.change_to('workspace');
+ frappe.workspace.route();
+ frappe.utils.set_title(__('Home'));
+ return;
}
frappe.model.with_doctype("Page", function() {
frappe.views.pageview.with_page(name, function(r) {
- if(r && r.exc) {
- if(!r['403'])
+ if (r && r.exc) {
+ if (!r['403'])
frappe.show_not_found(name);
- } else if(!frappe.pages[name]) {
+ } else if (!frappe.pages[name]) {
new frappe.views.Page(name);
}
frappe.container.change_to(name);
@@ -59,7 +75,7 @@ frappe.views.Page = class Page {
constructor(name) {
this.name = name;
var me = this;
-
+
// web home page
if(name==window.page_name) {
this.wrapper = document.getElementById('page-' + name);
@@ -87,7 +103,7 @@ frappe.views.Page = class Page {
}
this.trigger_page_event('on_page_load');
-
+
// set events
$(this.wrapper).on('show', function() {
window.cur_frm = null;
From 75fe8a615a2d28f77c78a9558debe32f364e262d Mon Sep 17 00:00:00 2001
From: Rushabh Mehta
Date: Wed, 11 Nov 2020 16:31:47 +0530
Subject: [PATCH 07/10] feat(app): move /desk to /app
---
cypress/integration/api.js | 2 +-
cypress/integration/awesome_bar.js | 4 ++--
cypress/integration/control_barcode.js | 2 +-
cypress/integration/control_duration.js | 2 +-
cypress/integration/control_link.js | 6 +++---
cypress/integration/control_rating.js | 2 +-
cypress/integration/datetime.js | 2 +-
cypress/integration/depends_on.js | 2 +-
cypress/integration/file_uploader.js | 2 +-
cypress/integration/form.js | 16 +++++++--------
cypress/integration/grid_pagination.js | 12 +++++------
cypress/integration/list_view.js | 2 +-
cypress/integration/list_view_settings.js | 6 +++---
cypress/integration/login.js | 2 +-
cypress/integration/query_report.js | 4 ++--
cypress/integration/recorder.js | 16 +++++++--------
cypress/integration/relative_time_filters.js | 6 +++---
cypress/integration/report_view.js | 4 ++--
cypress/support/commands.js | 4 ++--
frappe/__init__.py | 2 +-
frappe/auth.py | 2 +-
.../doctype/auto_repeat/auto_repeat.js | 2 +-
.../deleted_document/deleted_document_list.js | 2 +-
frappe/core/doctype/doctype/doctype.js | 4 ++--
.../core/doctype/log_settings/log_settings.py | 2 +-
frappe/core/doctype/user/user.py | 2 +-
.../permission_manager/permission_manager.js | 2 +-
.../permission_manager_help.html | 8 ++++----
.../customize_form/test_customize_form.py | 2 +-
frappe/desk/doctype/dashboard/dashboard.py | 2 +-
frappe/desk/moduleview.py | 8 ++++----
frappe/desk/page/leaderboard/leaderboard.js | 2 +-
frappe/desk/page/setup_wizard/setup_wizard.js | 2 +-
frappe/desk/report/todo/todo.py | 2 +-
.../doctype/notification/notification.js | 2 +-
.../google_calendar/google_calendar.js | 2 +-
.../google_calendar/google_calendar.py | 2 +-
.../google_contacts/google_contacts.js | 2 +-
.../google_contacts/google_contacts.py | 2 +-
.../doctype/google_drive/google_drive.js | 2 +-
.../doctype/google_drive/google_drive.py | 2 +-
frappe/model/delete_doc.py | 4 ++--
frappe/model/document.py | 4 ++--
frappe/public/js/frappe/form/form.js | 2 +-
frappe/public/js/frappe/form/formatters.js | 2 +-
frappe/public/js/frappe/form/linked_with.js | 2 +-
.../js/frappe/form/multi_select_dialog.js | 2 +-
.../frappe/form/templates/address_list.html | 2 +-
.../frappe/form/templates/contact_list.html | 2 +-
.../frappe/form/templates/print_layout.html | 2 +-
frappe/public/js/frappe/list/list_factory.js | 8 ++++----
frappe/public/js/frappe/list/list_view.js | 2 +-
frappe/public/js/frappe/recorder/recorder.js | 4 ++--
frappe/public/js/frappe/router.js | 20 ++++++++++++++-----
.../frappe/ui/notifications/notifications.js | 8 ++++----
.../js/frappe/utils/energy_point_utils.js | 2 +-
frappe/public/js/frappe/utils/utils.js | 2 +-
frappe/public/js/frappe/views/breadcrumbs.js | 4 ++--
.../public/js/frappe/views/file/file_view.js | 6 +++---
.../views/image/image_view_item_row.html | 2 +-
.../js/frappe/views/kanban/kanban_view.js | 2 +-
frappe/public/js/frappe/views/pageview.js | 16 ---------------
.../js/frappe/views/reports/query_report.js | 8 ++++----
.../js/frappe/views/workspace/workspace.js | 2 +-
.../js/frappe/widgets/onboarding_widget.js | 2 +-
frappe/public/js/frappe/widgets/utils.js | 1 -
.../energy_point_log/energy_point_log.js | 2 +-
.../templates/includes/comments/comments.py | 2 +-
.../includes/navbar/navbar_login.html | 2 +-
.../pages/integrations/gcalendar-success.html | 2 +-
frappe/utils/bot.py | 6 +++---
frappe/utils/csvutils.py | 2 +-
frappe/utils/data.py | 6 +++---
frappe/utils/oauth.py | 2 +-
.../website_settings/google_indexing.py | 2 +-
frappe/website/render.py | 5 ++---
.../workflow_action/workflow_action_list.js | 2 +-
frappe/www/{desk.html => app.html} | 1 -
frappe/www/{desk.py => app.py} | 3 +--
frappe/www/login.py | 2 +-
80 files changed, 147 insertions(+), 157 deletions(-)
rename frappe/www/{desk.html => app.html} (98%)
rename frappe/www/{desk.py => app.py} (96%)
diff --git a/cypress/integration/api.js b/cypress/integration/api.js
index 2279dc399d..cd91c8fae4 100644
--- a/cypress/integration/api.js
+++ b/cypress/integration/api.js
@@ -2,7 +2,7 @@ context('API Resources', () => {
before(() => {
cy.visit('/login');
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
});
it('Creates two Comments', () => {
diff --git a/cypress/integration/awesome_bar.js b/cypress/integration/awesome_bar.js
index 15e85976fc..dd56ca33f7 100644
--- a/cypress/integration/awesome_bar.js
+++ b/cypress/integration/awesome_bar.js
@@ -2,7 +2,7 @@ context('Awesome Bar', () => {
before(() => {
cy.visit('/login');
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
});
beforeEach(() => {
@@ -16,7 +16,7 @@ context('Awesome Bar', () => {
cy.get('h1').should('contain', 'To Do');
- cy.location('hash').should('eq', '#List/ToDo/List');
+ cy.location('hash').should('eq', '/app/List/ToDo/List');
});
it('find text in doctype list', () => {
diff --git a/cypress/integration/control_barcode.js b/cypress/integration/control_barcode.js
index 4e05d864e6..ea26f446f4 100644
--- a/cypress/integration/control_barcode.js
+++ b/cypress/integration/control_barcode.js
@@ -1,7 +1,7 @@
context('Control Barcode', () => {
beforeEach(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
});
function get_dialog_with_barcode() {
diff --git a/cypress/integration/control_duration.js b/cypress/integration/control_duration.js
index edad759216..fae207890f 100644
--- a/cypress/integration/control_duration.js
+++ b/cypress/integration/control_duration.js
@@ -1,7 +1,7 @@
context('Control Duration', () => {
before(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
});
function get_dialog_with_duration(hide_days=0, hide_seconds=0) {
diff --git a/cypress/integration/control_link.js b/cypress/integration/control_link.js
index 0dc7d5b88e..248271453b 100644
--- a/cypress/integration/control_link.js
+++ b/cypress/integration/control_link.js
@@ -1,11 +1,11 @@
context('Control Link', () => {
before(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
});
beforeEach(() => {
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
cy.create_records({
doctype: 'ToDo',
description: 'this is a test todo for link'
@@ -77,7 +77,7 @@ context('Control Link', () => {
cy.get('.frappe-control[data-fieldname=link] .link-btn')
.should('be.visible')
.click();
- cy.location('hash').should('eq', `#Form/ToDo/${todos[0]}`);
+ cy.location('hash').should('eq', `/app/Form/ToDo/${todos[0]}`);
});
});
});
diff --git a/cypress/integration/control_rating.js b/cypress/integration/control_rating.js
index e89ab2d3be..c1e308860e 100644
--- a/cypress/integration/control_rating.js
+++ b/cypress/integration/control_rating.js
@@ -1,7 +1,7 @@
context('Control Rating', () => {
before(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
});
function get_dialog_with_rating() {
diff --git a/cypress/integration/datetime.js b/cypress/integration/datetime.js
index 9bf01632bf..7a9f51fb0d 100644
--- a/cypress/integration/datetime.js
+++ b/cypress/integration/datetime.js
@@ -4,7 +4,7 @@ const doctype_name = datetime_doctype.name;
context('Control Date, Time and DateTime', () => {
before(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
return cy.insert_doc('DocType', datetime_doctype, true);
});
diff --git a/cypress/integration/depends_on.js b/cypress/integration/depends_on.js
index 93417014c5..919323dcc3 100644
--- a/cypress/integration/depends_on.js
+++ b/cypress/integration/depends_on.js
@@ -1,7 +1,7 @@
context('Depends On', () => {
before(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
return cy.window().its('frappe').then(frappe => {
return frappe.call('frappe.tests.ui_test_helpers.create_doctype', {
name: 'Test Depends On',
diff --git a/cypress/integration/file_uploader.js b/cypress/integration/file_uploader.js
index f9f44675db..4186141870 100644
--- a/cypress/integration/file_uploader.js
+++ b/cypress/integration/file_uploader.js
@@ -1,7 +1,7 @@
context('FileUploader', () => {
before(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
});
function open_upload_dialog() {
diff --git a/cypress/integration/form.js b/cypress/integration/form.js
index ef89a18e7d..d804ec8d99 100644
--- a/cypress/integration/form.js
+++ b/cypress/integration/form.js
@@ -1,13 +1,13 @@
context('Form', () => {
before(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
return cy.window().its('frappe').then(frappe => {
return frappe.call("frappe.tests.ui_test_helpers.create_contact_records");
});
});
it('create a new form', () => {
- cy.visit('/desk#Form/ToDo/New ToDo 1');
+ cy.visit('/app/Form/ToDo/New ToDo 1');
cy.fill_field('description', 'this is a test todo', 'Text Editor').blur();
cy.wait(300);
cy.get('.page-title').should('contain', 'Not Saved');
@@ -18,20 +18,20 @@ context('Form', () => {
}).as('form_save');
cy.get('.primary-action').click();
cy.wait('@form_save').its('status').should('eq', 200);
- cy.visit('/desk#List/ToDo');
- cy.location('hash').should('eq', '#List/ToDo/List');
+ cy.visit('/app/List/ToDo');
+ cy.location('hash').should('eq', '/app/List/ToDo/List');
cy.get('h1').should('be.visible').and('contain', 'To Do');
cy.get('.list-row').should('contain', 'this is a test todo');
});
it('navigates between documents with child table list filters applied', () => {
- cy.visit('/desk#List/Contact');
- cy.location('hash').should('eq', '#List/Contact/List');
+ cy.visit('/app/List/Contact');
+ cy.location('hash').should('eq', '/app/List/Contact/List');
cy.get('.tag-filters-area .btn:contains("Add Filter")').click();
cy.get('.fieldname-select-area').should('exist');
cy.get('.fieldname-select-area input').type('Number{enter}', { force: true });
cy.get('.filter-field .input-with-feedback.form-control').type('123', { force: true });
cy.get('.filter-box .btn:contains("Apply")').click({ force: true });
- cy.visit('/desk#Form/Contact/Test Form Contact 3');
+ cy.visit('/app/Form/Contact/Test Form Contact 3');
cy.get('.prev-doc').should('be.visible').click();
cy.get('.msgprint-dialog .modal-body').contains('No further records').should('be.visible');
cy.get('.btn-modal-close:visible').click();
@@ -50,7 +50,7 @@ context('Form', () => {
let website_input = 'website.in';
let expectBackgroundColor = 'rgb(255, 220, 220)';
- cy.visit('/desk#Form/Contact/New Contact 1');
+ cy.visit('/app/Form/Contact/New Contact 1');
cy.get('.frappe-control[data-fieldname="email_ids"]').as('table');
cy.get('@table').find('button.grid-add-row').click();
cy.get('.grid-body .rows [data-fieldname="email_id"]').click();
diff --git a/cypress/integration/grid_pagination.js b/cypress/integration/grid_pagination.js
index b383f30bb8..7142dce131 100644
--- a/cypress/integration/grid_pagination.js
+++ b/cypress/integration/grid_pagination.js
@@ -1,24 +1,24 @@
context('Grid Pagination', () => {
beforeEach(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
});
before(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
return cy.window().its('frappe').then(frappe => {
return frappe.call("frappe.tests.ui_test_helpers.create_contact_phone_nos_records");
});
});
it('creates pages for child table', () => {
- cy.visit('/desk#Form/Contact/Test Contact');
+ cy.visit('/app/Form/Contact/Test Contact');
cy.get('.frappe-control[data-fieldname="phone_nos"]').as('table');
cy.get('@table').find('.current-page-number').should('contain', '1');
cy.get('@table').find('.total-page-number').should('contain', '20');
cy.get('@table').find('.grid-body .grid-row').should('have.length', 50);
});
it('goes to the next and previous page', () => {
- cy.visit('/desk#Form/Contact/Test Contact');
+ cy.visit('/app/Form/Contact/Test Contact');
cy.get('.frappe-control[data-fieldname="phone_nos"]').as('table');
cy.get('@table').find('.next-page').click();
cy.get('@table').find('.current-page-number').should('contain', '2');
@@ -28,7 +28,7 @@ context('Grid Pagination', () => {
cy.get('@table').find('.grid-body .grid-row').first().should('have.attr', 'data-idx', '1');
});
it('adds and deletes rows and changes page', ()=> {
- cy.visit('/desk#Form/Contact/Test Contact');
+ cy.visit('/app/Form/Contact/Test Contact');
cy.get('.frappe-control[data-fieldname="phone_nos"]').as('table');
cy.get('@table').find('button.grid-add-row').click();
cy.get('@table').find('.grid-body .row-index').should('contain', 1001);
@@ -41,7 +41,7 @@ context('Grid Pagination', () => {
cy.get('@table').find('.total-page-number').should('contain', '20');
});
// it('deletes all rows', ()=> {
- // cy.visit('/desk#Form/Contact/Test Contact');
+ // cy.visit('/app/Form/Contact/Test Contact');
// cy.get('.frappe-control[data-fieldname="phone_nos"]').as('table');
// cy.get('@table').find('.grid-heading-row .grid-row-check').click({force: true});
// cy.get('@table').find('button.grid-remove-all-rows').click();
diff --git a/cypress/integration/list_view.js b/cypress/integration/list_view.js
index 0d26ca90a2..bb93d320bb 100644
--- a/cypress/integration/list_view.js
+++ b/cypress/integration/list_view.js
@@ -1,7 +1,7 @@
context('List View', () => {
before(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
return cy.window().its('frappe').then(frappe => {
return frappe.xcall("frappe.tests.ui_test_helpers.setup_workflow");
});
diff --git a/cypress/integration/list_view_settings.js b/cypress/integration/list_view_settings.js
index 47f8efe94b..5979185dcf 100644
--- a/cypress/integration/list_view_settings.js
+++ b/cypress/integration/list_view_settings.js
@@ -1,16 +1,16 @@
context('List View Settings', () => {
beforeEach(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
});
it('Default settings', () => {
- cy.visit('/desk#List/DocType/List');
+ cy.visit('/app/List/DocType/List');
cy.get('.list-count').should('contain', "20 of");
cy.get('.sidebar-stat').should('contain', "Tags");
});
it('disable count and sidebar stats then verify', () => {
cy.wait(300);
- cy.visit('/desk#List/DocType/List');
+ cy.visit('/app/List/DocType/List');
cy.wait(300);
cy.get('.list-count').should('contain', "20 of");
cy.get('button').contains('Menu').click();
diff --git a/cypress/integration/login.js b/cypress/integration/login.js
index 861377444c..e8964768b0 100644
--- a/cypress/integration/login.js
+++ b/cypress/integration/login.js
@@ -35,7 +35,7 @@ context('Login', () => {
cy.get('#login_password').type(Cypress.config('adminPassword'));
cy.get('.btn-login').click();
- cy.location('pathname').should('eq', '/desk');
+ cy.location('pathname').should('eq', '/app');
cy.window().its('frappe.session.user').should('eq', 'Administrator');
});
diff --git a/cypress/integration/query_report.js b/cypress/integration/query_report.js
index 5581a20edc..b06295495a 100644
--- a/cypress/integration/query_report.js
+++ b/cypress/integration/query_report.js
@@ -1,11 +1,11 @@
context('Query Report', () => {
before(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
});
it('add custom column in report', () => {
- cy.visit('/desk#query-report/Permitted Documents For User');
+ cy.visit('/app#query-report/Permitted Documents For User');
cy.get('div[class="page-form flex"]', {timeout: 60000}).should('have.length', 1).then(()=>{
cy.get('#page-query-report input[data-fieldname="user"]').as('input');
diff --git a/cypress/integration/recorder.js b/cypress/integration/recorder.js
index a0f8cc3621..e89621d936 100644
--- a/cypress/integration/recorder.js
+++ b/cypress/integration/recorder.js
@@ -4,14 +4,14 @@ context('Recorder', () => {
});
it('Navigate to Recorder', () => {
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
cy.awesomebar('recorder');
cy.get('h1').should('contain', 'Recorder');
cy.location('hash').should('eq', '#recorder');
});
it('Recorder Empty State', () => {
- cy.visit('/desk#recorder');
+ cy.visit('/app#recorder');
cy.get('.title-text').should('contain', 'Recorder');
cy.get('.indicator').should('contain', 'Inactive').should('have.class', 'red');
@@ -24,21 +24,21 @@ context('Recorder', () => {
});
it('Recorder Start', () => {
- cy.visit('/desk#recorder');
+ cy.visit('/app#recorder');
cy.get('.primary-action').should('contain', 'Start').click();
cy.get('.indicator').should('contain', 'Active').should('have.class', 'green');
cy.get('.msg-box').should('contain', 'No Requests');
cy.server();
- cy.visit('/desk#List/DocType/List');
+ cy.visit('/app/List/DocType/List');
cy.route('POST', '/api/method/frappe.desk.reportview.get').as('list_refresh');
cy.wait('@list_refresh');
cy.get('.title-text').should('contain', 'DocType');
cy.get('.list-count').should('contain', '20 of ');
- cy.visit('/desk#recorder');
+ cy.visit('/app#recorder');
cy.get('.title-text').should('contain', 'Recorder');
cy.get('.result-list').should('contain', '/api/method/frappe.desk.reportview.get');
@@ -48,11 +48,11 @@ context('Recorder', () => {
});
it('Recorder View Request', () => {
- cy.visit('/desk#recorder');
+ cy.visit('/app#recorder');
cy.get('.primary-action').should('contain', 'Start').click();
cy.server();
- cy.visit('/desk#List/DocType/List');
+ cy.visit('/app/List/DocType/List');
cy.route('POST', '/api/method/frappe.desk.reportview.get').as('list_refresh');
cy.wait('@list_refresh');
@@ -62,7 +62,7 @@ context('Recorder', () => {
// temporarily commenting out theses tests as they seem to be
// randomly failing maybe due a backround event
- // cy.visit('/desk#recorder');
+ // cy.visit('/app#recorder');
// cy.get('.list-row-container span').contains('/api/method/frappe').click();
diff --git a/cypress/integration/relative_time_filters.js b/cypress/integration/relative_time_filters.js
index ac70c44345..c13c2bbb5e 100644
--- a/cypress/integration/relative_time_filters.js
+++ b/cypress/integration/relative_time_filters.js
@@ -4,13 +4,13 @@ context('Relative Timeframe', () => {
});
before(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
cy.window().its('frappe').then(frappe => {
frappe.call("frappe.tests.ui_test_helpers.create_todo_records");
});
});
it('sets relative timespan filter for last week and filters list', () => {
- cy.visit('/desk#List/ToDo/List');
+ cy.visit('/app/List/ToDo/List');
cy.get('.list-row:contains("this is fourth todo")').should('exist');
cy.get('.tag-filters-area .btn:contains("Add Filter")').click();
cy.get('.fieldname-select-area').should('exist');
@@ -29,7 +29,7 @@ context('Relative Timeframe', () => {
cy.wait('@save_user_settings');
});
it('sets relative timespan filter for next week and filters list', () => {
- cy.visit('/desk#List/ToDo/List');
+ cy.visit('/app/List/ToDo/List');
cy.get('.list-row:contains("this is fourth todo")').should('exist');
cy.get('.tag-filters-area .btn:contains("Add Filter")').click();
cy.get('.fieldname-select-area input').type("Due Date{enter}", { delay: 100 });
diff --git a/cypress/integration/report_view.js b/cypress/integration/report_view.js
index deeef6bdd5..af84c44cdc 100644
--- a/cypress/integration/report_view.js
+++ b/cypress/integration/report_view.js
@@ -4,7 +4,7 @@ const doctype_name = custom_submittable_doctype.name;
context('Report View', () => {
before(() => {
cy.login();
- cy.visit('/desk#workspace/Website');
+ cy.visit('/app#workspace/Website');
cy.insert_doc('DocType', custom_submittable_doctype, true);
cy.clear_cache();
cy.insert_doc(doctype_name, {
@@ -18,7 +18,7 @@ context('Report View', () => {
it('Field with enabled allow_on_submit should be editable.', () => {
cy.server();
cy.route('POST', 'api/method/frappe.client.set_value').as('value-update');
- cy.visit(`/desk#List/${doctype_name}/Report`);
+ cy.visit(`/app/List/${doctype_name}/Report`);
// check status column added from docstatus
cy.get('.dt-row-0 > .dt-cell--col-3').should('contain', 'Submitted');
let cell = cy.get('.dt-row-0 > .dt-cell--col-4');
diff --git a/cypress/support/commands.js b/cypress/support/commands.js
index 7816d5526f..c3f2deed20 100644
--- a/cypress/support/commands.js
+++ b/cypress/support/commands.js
@@ -210,13 +210,13 @@ Cypress.Commands.add('awesomebar', text => {
Cypress.Commands.add('new_form', doctype => {
let route = `Form/${doctype}/New ${doctype} 1`;
- cy.visit(`/desk#${route}`);
+ cy.visit(`/app#${route}`);
cy.get('body').should('have.attr', 'data-route', route);
cy.get('body').should('have.attr', 'data-ajax-state', 'complete');
});
Cypress.Commands.add('go_to_list', doctype => {
- cy.visit(`/desk#List/${doctype}/List`);
+ cy.visit(`/app/List/${doctype}/List`);
});
Cypress.Commands.add('clear_cache', () => {
diff --git a/frappe/__init__.py b/frappe/__init__.py
index fac0927428..52869be3dc 100644
--- a/frappe/__init__.py
+++ b/frappe/__init__.py
@@ -1611,7 +1611,7 @@ def log_error(message=None, title=_("Error")):
method=title)).insert(ignore_permissions=True)
def get_desk_link(doctype, name):
- html = '{doctype_local} {name}'
+ html = '{doctype_local} {name}'
return html.format(
doctype=doctype,
name=name,
diff --git a/frappe/auth.py b/frappe/auth.py
index 3b18c8adb9..3f2e12b416 100644
--- a/frappe/auth.py
+++ b/frappe/auth.py
@@ -167,7 +167,7 @@ class LoginManager:
frappe.local.cookie_manager.set_cookie("system_user", "yes")
if not resume:
frappe.local.response['message'] = 'Logged In'
- frappe.local.response["home_page"] = "/desk"
+ frappe.local.response["home_page"] = "/app"
if not resume:
frappe.response["full_name"] = self.full_name
diff --git a/frappe/automation/doctype/auto_repeat/auto_repeat.js b/frappe/automation/doctype/auto_repeat/auto_repeat.js
index 456061ee0b..7d6bf69e3d 100644
--- a/frappe/automation/doctype/auto_repeat/auto_repeat.js
+++ b/frappe/automation/doctype/auto_repeat/auto_repeat.js
@@ -30,7 +30,7 @@ frappe.ui.form.on('Auto Repeat', {
refresh: function(frm) {
// auto repeat message
if (frm.is_new()) {
- let customize_form_link = `${__('Customize Form')}`;
+ let customize_form_link = `${__('Customize Form')}`;
frm.dashboard.set_headline(__('To configure Auto Repeat, enable "Allow Auto Repeat" from {0}.', [customize_form_link]));
}
diff --git a/frappe/core/doctype/deleted_document/deleted_document_list.js b/frappe/core/doctype/deleted_document/deleted_document_list.js
index f5e1147dfb..81a8992a19 100644
--- a/frappe/core/doctype/deleted_document/deleted_document_list.js
+++ b/frappe/core/doctype/deleted_document/deleted_document_list.js
@@ -11,7 +11,7 @@ frappe.listview_settings["Deleted Document"] = {
if (r.message) {
function body(docnames) {
const html = docnames.map(docname => {
- return `${docname}`;
+ return `${docname}`;
});
return "
" + html.join("");
}
diff --git a/frappe/core/doctype/doctype/doctype.js b/frappe/core/doctype/doctype/doctype.js
index e236464b95..d4fe53aea3 100644
--- a/frappe/core/doctype/doctype/doctype.js
+++ b/frappe/core/doctype/doctype/doctype.js
@@ -24,12 +24,12 @@ frappe.ui.form.on('DocType', {
if (!frm.is_new() && !frm.doc.istable) {
if (frm.doc.issingle) {
frm.add_custom_button(__('Go to {0}', [frm.doc.name]), () => {
- window.open(`/desk#Form/${frm.doc.name}`);
+ window.open(`/app/Form/${frm.doc.name}`);
// frappe.set_route('Form', frm.doc.name);
});
} else {
frm.add_custom_button(__('Go to {0} List', [frm.doc.name]), () => {
- window.open(`/desk#List/${frm.doc.name}/List`);
+ window.open(`/app/List/${frm.doc.name}/List`);
});
}
}
diff --git a/frappe/core/doctype/log_settings/log_settings.py b/frappe/core/doctype/log_settings/log_settings.py
index 6d59cdeb29..08e61d3289 100644
--- a/frappe/core/doctype/log_settings/log_settings.py
+++ b/frappe/core/doctype/log_settings/log_settings.py
@@ -36,7 +36,7 @@ def has_unseen_error_log(user):
def _get_response(show_alert=True):
return {
'show_alert': True,
- 'message': _("You have unseen {0}").format(' Error Logs ')
+ 'message': _("You have unseen {0}").format(' Error Logs ')
}
if frappe.db.sql_list("select name from `tabError Log` where seen = 0 limit 1"):
diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py
index 9fc6658f29..d27107213b 100644
--- a/frappe/core/doctype/user/user.py
+++ b/frappe/core/doctype/user/user.py
@@ -577,7 +577,7 @@ def update_password(new_password, logout_all_sessions=0, key=None, old_password=
frappe.db.set_value("User", user, "reset_password_key", "")
if user_doc.user_type == "System User":
- return "/desk"
+ return "/app"
else:
return redirect_url if redirect_url else "/"
diff --git a/frappe/core/page/permission_manager/permission_manager.js b/frappe/core/page/permission_manager/permission_manager.js
index 0038975162..8d00952e8d 100644
--- a/frappe/core/page/permission_manager/permission_manager.js
+++ b/frappe/core/page/permission_manager/permission_manager.js
@@ -311,7 +311,7 @@ frappe.PermissionEngine = class PermissionEngine {
},
callback: function (r) {
r.message = $.map(r.message, function (p) {
- return $.format('{1}', [p, p]);
+ return $.format('{1}', [p, p]);
});
frappe.msgprint(__("Users with role {0}:", [__(role)])
+ "
" + r.message.join("
"));
diff --git a/frappe/core/page/permission_manager/permission_manager_help.html b/frappe/core/page/permission_manager/permission_manager_help.html
index 30ccbed92f..0613713e81 100644
--- a/frappe/core/page/permission_manager/permission_manager_help.html
+++ b/frappe/core/page/permission_manager/permission_manager_help.html
@@ -5,8 +5,8 @@
- {%= __("Permissions are set on Roles and Document Types (called DocTypes) by setting rights like Read, Write, Create, Delete, Submit, Cancel, Amend, Report, Import, Export, Print, Email and Set User Permissions.") %}
- {%= __("Permissions get applied on Users based on what Roles they are assigned.") %}
- {%= __("Roles can be set for users from their User page.") %}
- {%= __("Setup > User") %}
- - {%= __("The system provides many pre-defined roles. You can add new roles to set finer permissions.") %} {%= __("Add a New Role") %}
+ {%= __("Setup > User") %}
+ - {%= __("The system provides many pre-defined roles. You can add new roles to set finer permissions.") %} {%= __("Add a New Role") %}
- {%= __("Permissions are automatically applied to Standard Reports and searches.") %}
- {%= __("As a best practice, do not assign the same set of permission rule to different Roles. Instead, set multiple Roles to the same User.") %}
@@ -24,13 +24,13 @@
- {%= __("Permissions at level 0 are Document Level permissions, i.e. they are primary for access to the document.") %}
- {%= __("If a Role does not have access at Level 0, then higher levels are meaningless.") %}
- {%= __("Permissions at higher levels are Field Level permissions. All Fields have a Permission Level set against them and the rules defined at that permissions apply to the field. This is useful in case you want to hide or make certain field read-only for certain Roles.") %}
- - {%= __("You can use Customize Form to set levels on fields.") %} {%= __("Setup > Customize Form") %}
+ - {%= __("You can use Customize Form to set levels on fields.") %} {%= __("Setup > Customize Form") %}
{%= __("User Permissions") %}:
- {%= __("User Permissions are used to limit users to specific records.") %}
- {%= __("Setup > User Permissions") %}
+ {%= __("Setup > User Permissions") %}
- {%= __("Select Document Types to set which User Permissions are used to limit access.") %}
- {%= __("Once you have set this, the users will only be able access documents (eg. Blog Post) where the link exists (eg. Blogger).") %}
- {%= __("Apart from System Manager, roles with Set User Permissions right can set permissions for other users for that Document Type.") %}
diff --git a/frappe/custom/doctype/customize_form/test_customize_form.py b/frappe/custom/doctype/customize_form/test_customize_form.py
index 46a2f2f9df..f5e0371c1f 100644
--- a/frappe/custom/doctype/customize_form/test_customize_form.py
+++ b/frappe/custom/doctype/customize_form/test_customize_form.py
@@ -234,7 +234,7 @@ class TestCustomizeForm(unittest.TestCase):
testdt1.delete()
def test_custom_action(self):
- test_route = '#List/DocType'
+ test_route = '/app/List/DocType'
# create a dummy action (route)
d = self.get_customize_form("Event")
diff --git a/frappe/desk/doctype/dashboard/dashboard.py b/frappe/desk/doctype/dashboard/dashboard.py
index b12bcfe27d..54bbc61e25 100644
--- a/frappe/desk/doctype/dashboard/dashboard.py
+++ b/frappe/desk/doctype/dashboard/dashboard.py
@@ -80,7 +80,7 @@ def get_non_standard_warning_message(non_standard_docs_map):
def get_html(docs, doctype):
html = '{}
'.format(frappe.bold(doctype))
for doc in docs:
- html += ''.format(doctype=doctype, doc=doc)
+ html += ''.format(doctype=doctype, doc=doc)
html += '
'
return html
diff --git a/frappe/desk/moduleview.py b/frappe/desk/moduleview.py
index ad696520f8..94882d86b5 100644
--- a/frappe/desk/moduleview.py
+++ b/frappe/desk/moduleview.py
@@ -12,7 +12,7 @@ from frappe.cache_manager import build_domain_restriced_doctype_cache, build_dom
@frappe.whitelist()
def get(module):
"""Returns data (sections, list of reports, counts) to render module view in desk:
- `/desk/#Module/[name]`."""
+ `/app/#Module/[name]`."""
data = get_data(module)
out = {
@@ -90,7 +90,7 @@ def get_data(module, build=True):
return data
def build_config_from_file(module):
- """Build module info from `app/config/desktop.py` files."""
+ """Build module info from `app/config/apptop.py` files."""
data = []
module = frappe.scrub(module)
@@ -150,7 +150,7 @@ def add_section(data, label, icon, items):
def add_custom_doctypes(data, doctype_info):
- """Adds Custom DocTypes to modules setup via `config/desktop.py`."""
+ """Adds Custom DocTypes to modules setup via `config/apptop.py`."""
add_section(data, _("Documents"), "fa fa-star",
[d for d in doctype_info if (d.custom and d.document_type in ("Document", "Transaction"))])
@@ -258,7 +258,7 @@ def config_exists(app, module):
return False
def add_setup_section(config, app, module, label, icon):
- """Add common sections to `/desk#Module/Setup`"""
+ """Add common sections to `/app#Module/Setup`"""
try:
setup_section = get_setup_section(app, module, label, icon)
if setup_section:
diff --git a/frappe/desk/page/leaderboard/leaderboard.js b/frappe/desk/page/leaderboard/leaderboard.js
index f49078401a..5209dc0fab 100644
--- a/frappe/desk/page/leaderboard/leaderboard.js
+++ b/frappe/desk/page/leaderboard/leaderboard.js
@@ -348,7 +348,7 @@ class Leaderboard {
return fieldname === this.options.selected_filter_item;
}));
- const link = `#Form/${this.options.selected_doctype}/${item.name}`;
+ const link = `/app/Form/${this.options.selected_doctype}/${item.name}`;
const name_html = item.formatted_name ?
`${item.formatted_name}`
: ` ${item.name} `;
diff --git a/frappe/desk/page/setup_wizard/setup_wizard.js b/frappe/desk/page/setup_wizard/setup_wizard.js
index eca21e8cab..9bdeecb51d 100644
--- a/frappe/desk/page/setup_wizard/setup_wizard.js
+++ b/frappe/desk/page/setup_wizard/setup_wizard.js
@@ -212,7 +212,7 @@ frappe.setup.SetupWizard = class SetupWizard extends frappe.ui.Slides {
}
setTimeout(function () {
// Reload
- window.location.href = '/desk';
+ window.location.href = '/app';
}, 2000);
}
diff --git a/frappe/desk/report/todo/todo.py b/frappe/desk/report/todo/todo.py
index a51d44fe08..f4fe2dc805 100644
--- a/frappe/desk/report/todo/todo.py
+++ b/frappe/desk/report/todo/todo.py
@@ -24,7 +24,7 @@ def execute(filters=None):
for todo in todo_list:
if todo.owner==frappe.session.user or todo.assigned_by==frappe.session.user:
if todo.reference_type:
- todo.reference = """%s: %s""" % (todo.reference_type,
+ todo.reference = """%s: %s""" % (todo.reference_type,
todo.reference_name, todo.reference_type, todo.reference_name)
else:
todo.reference = None
diff --git a/frappe/email/doctype/notification/notification.js b/frappe/email/doctype/notification/notification.js
index 2cc027acd6..e5346da755 100644
--- a/frappe/email/doctype/notification/notification.js
+++ b/frappe/email/doctype/notification/notification.js
@@ -203,7 +203,7 @@ frappe.ui.form.on('Notification', {
frappe.notification.setup_example_message(frm);
if (frm.doc.channel === 'SMS' && frm.doc.__islocal) {
frm.set_df_property('channel',
- 'description', `To use SMS Channel, initialize SMS Settings.`);
+ 'description', `To use SMS Channel, initialize SMS Settings.`);
} else {
frm.set_df_property('channel', 'description', ` `);
}
diff --git a/frappe/integrations/doctype/google_calendar/google_calendar.js b/frappe/integrations/doctype/google_calendar/google_calendar.js
index f941cf0575..198c8e2706 100644
--- a/frappe/integrations/doctype/google_calendar/google_calendar.js
+++ b/frappe/integrations/doctype/google_calendar/google_calendar.js
@@ -4,7 +4,7 @@
frappe.ui.form.on("Google Calendar", {
refresh: function(frm) {
if (frm.is_new()) {
- frm.dashboard.set_headline(__("To use Google Calendar, enable {0}.", [`${__('Google Settings')}`]));
+ frm.dashboard.set_headline(__("To use Google Calendar, enable {0}.", [`${__('Google Settings')}`]));
}
frappe.realtime.on("import_google_calendar", (data) => {
diff --git a/frappe/integrations/doctype/google_calendar/google_calendar.py b/frappe/integrations/doctype/google_calendar/google_calendar.py
index 4a9acd9e84..fbedd75029 100644
--- a/frappe/integrations/doctype/google_calendar/google_calendar.py
+++ b/frappe/integrations/doctype/google_calendar/google_calendar.py
@@ -120,7 +120,7 @@ def authorize_access(g_calendar, reauthorize=None):
frappe.db.commit()
frappe.local.response["type"] = "redirect"
- frappe.local.response["location"] = "/desk#Form/{0}/{1}".format(quote("Google Calendar"), quote(google_calendar.name))
+ frappe.local.response["location"] = "/app/Form/{0}/{1}".format(quote("Google Calendar"), quote(google_calendar.name))
frappe.msgprint(_("Google Calendar has been configured."))
except Exception as e:
diff --git a/frappe/integrations/doctype/google_contacts/google_contacts.js b/frappe/integrations/doctype/google_contacts/google_contacts.js
index af194d4978..029821b3bb 100644
--- a/frappe/integrations/doctype/google_contacts/google_contacts.js
+++ b/frappe/integrations/doctype/google_contacts/google_contacts.js
@@ -4,7 +4,7 @@
frappe.ui.form.on('Google Contacts', {
refresh: function(frm) {
if (!frm.doc.enable) {
- frm.dashboard.set_headline(__("To use Google Contacts, enable {0}.", [`${__('Google Settings')}`]));
+ frm.dashboard.set_headline(__("To use Google Contacts, enable {0}.", [`${__('Google Settings')}`]));
}
frappe.realtime.on('import_google_contacts', (data) => {
diff --git a/frappe/integrations/doctype/google_contacts/google_contacts.py b/frappe/integrations/doctype/google_contacts/google_contacts.py
index 6455623281..4c8c3b67f6 100644
--- a/frappe/integrations/doctype/google_contacts/google_contacts.py
+++ b/frappe/integrations/doctype/google_contacts/google_contacts.py
@@ -79,7 +79,7 @@ def authorize_access(g_contact, reauthorize=None):
frappe.db.commit()
frappe.local.response["type"] = "redirect"
- frappe.local.response["location"] = "/desk#Form/Google%20Contacts/{}".format(google_contact.name)
+ frappe.local.response["location"] = "/app/Form/Google%20Contacts/{}".format(google_contact.name)
frappe.msgprint(_("Google Contacts has been configured."))
except Exception as e:
diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js
index f184c6d75c..1463f8725d 100644
--- a/frappe/integrations/doctype/google_drive/google_drive.js
+++ b/frappe/integrations/doctype/google_drive/google_drive.js
@@ -4,7 +4,7 @@
frappe.ui.form.on('Google Drive', {
refresh: function(frm) {
if (!frm.doc.enable) {
- frm.dashboard.set_headline(__("To use Google Drive, enable {0}.", [`${__('Google Settings')}`]));
+ frm.dashboard.set_headline(__("To use Google Drive, enable {0}.", [`${__('Google Settings')}`]));
}
frappe.realtime.on("upload_to_google_drive", (data) => {
diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py
index c1c73d7726..859c769018 100644
--- a/frappe/integrations/doctype/google_drive/google_drive.py
+++ b/frappe/integrations/doctype/google_drive/google_drive.py
@@ -88,7 +88,7 @@ def authorize_access(reauthorize=None):
frappe.db.commit()
frappe.local.response["type"] = "redirect"
- frappe.local.response["location"] = "/desk#Form/{0}".format(quote("Google Drive"))
+ frappe.local.response["location"] = "/app/Form/{0}".format(quote("Google Drive"))
frappe.msgprint(_("Google Drive has been configured."))
except Exception as e:
diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py
index a38470e3f5..688ecbe40f 100644
--- a/frappe/model/delete_doc.py
+++ b/frappe/model/delete_doc.py
@@ -287,8 +287,8 @@ def check_if_doc_is_dynamically_linked(doc, method="Delete"):
raise_link_exists_exception(doc, reference_doctype, reference_docname, at_position)
def raise_link_exists_exception(doc, reference_doctype, reference_docname, row=''):
- doc_link = '{1}'.format(doc.doctype, doc.name)
- reference_link = '{1}'.format(reference_doctype, reference_docname)
+ doc_link = '{1}'.format(doc.doctype, doc.name)
+ reference_link = '{1}'.format(reference_doctype, reference_docname)
#hack to display Single doctype only once in message
if reference_doctype == reference_docname:
diff --git a/frappe/model/document.py b/frappe/model/document.py
index 3789e20b19..d17025538b 100644
--- a/frappe/model/document.py
+++ b/frappe/model/document.py
@@ -1188,8 +1188,8 @@ class Document(BaseDocument):
doc.set(fieldname, flt(doc.get(fieldname), self.precision(fieldname, doc.parentfield)))
def get_url(self):
- """Returns Desk URL for this document. `/desk#Form/{doctype}/{name}`"""
- return "/desk#Form/{doctype}/{name}".format(doctype=self.doctype, name=self.name)
+ """Returns Desk URL for this document. `/app/Form/{doctype}/{name}`"""
+ return "/app/Form/{doctype}/{name}".format(doctype=self.doctype, name=self.name)
def add_comment(self, comment_type='Comment', text=None, comment_email=None, link_doctype=None, link_name=None, comment_by=None):
"""Add a comment to this document.
diff --git a/frappe/public/js/frappe/form/form.js b/frappe/public/js/frappe/form/form.js
index 837fa09b1f..26dee5c831 100644
--- a/frappe/public/js/frappe/form/form.js
+++ b/frappe/public/js/frappe/form/form.js
@@ -1522,7 +1522,7 @@ frappe.ui.form.Form = class FrappeForm {
const escaped_name = encodeURIComponent(value);
- return repl('%(label)s', {
+ return repl('%(label)s', {
color: get_color(doc || {}),
doctype: df.options,
escaped_name: escaped_name,
diff --git a/frappe/public/js/frappe/form/formatters.js b/frappe/public/js/frappe/form/formatters.js
index bebe4e4065..49df313679 100644
--- a/frappe/public/js/frappe/form/formatters.js
+++ b/frappe/public/js/frappe/form/formatters.js
@@ -121,7 +121,7 @@ frappe.form.formatters = {
{onclick: docfield.link_onclick.replace(/"/g, '"'), value:value});
} else if(docfield && doctype) {
return `
${__(options && options.label || value)}`
diff --git a/frappe/public/js/frappe/form/linked_with.js b/frappe/public/js/frappe/form/linked_with.js
index d8e07f8303..c5ed00add4 100644
--- a/frappe/public/js/frappe/form/linked_with.js
+++ b/frappe/public/js/frappe/form/linked_with.js
@@ -157,7 +157,7 @@ frappe.ui.form.LinkedWith = class LinkedWith {
return ``;
diff --git a/frappe/public/js/frappe/form/multi_select_dialog.js b/frappe/public/js/frappe/form/multi_select_dialog.js
index a0bb927563..a9e8c2b0d2 100644
--- a/frappe/public/js/frappe/form/multi_select_dialog.js
+++ b/frappe/public/js/frappe/form/multi_select_dialog.js
@@ -236,7 +236,7 @@ frappe.ui.form.MultiSelectDialog = class MultiSelectDialog {
${
head ? `${__(frappe.model.unscrub(column))}`
: (column !== "name" ? `${__(result[column] || '')}`
- : `
+ : `
${__(result[column] || '')}`)}
`;
});
diff --git a/frappe/public/js/frappe/form/templates/address_list.html b/frappe/public/js/frappe/form/templates/address_list.html
index 0f967b67a0..a6b8bf1377 100644
--- a/frappe/public/js/frappe/form/templates/address_list.html
+++ b/frappe/public/js/frappe/form/templates/address_list.html
@@ -9,7 +9,7 @@
{% if(addr_list[i].is_shipping_address) { %}
({%= __("Shipping") %}){% } %}
-
{%= __("Edit") %}
diff --git a/frappe/public/js/frappe/form/templates/contact_list.html b/frappe/public/js/frappe/form/templates/contact_list.html
index a967498d0f..e5fdc3f88e 100644
--- a/frappe/public/js/frappe/form/templates/contact_list.html
+++ b/frappe/public/js/frappe/form/templates/contact_list.html
@@ -9,7 +9,7 @@
{% if(contact_list[i].designation){ %}
– {%= contact_list[i].designation %}
{% } %}
-
{%= __("Edit") %}
diff --git a/frappe/public/js/frappe/form/templates/print_layout.html b/frappe/public/js/frappe/form/templates/print_layout.html
index 5ee9f572f3..366a771218 100644
--- a/frappe/public/js/frappe/form/templates/print_layout.html
+++ b/frappe/public/js/frappe/form/templates/print_layout.html
@@ -31,7 +31,7 @@