diff --git a/frappe/boot.py b/frappe/boot.py index a2911a9eff..c4f0c42f74 100644 --- a/frappe/boot.py +++ b/frappe/boot.py @@ -9,7 +9,7 @@ bootstrap client session import frappe import frappe.defaults import frappe.desk.desk_page -from frappe.utils import get_gravatar +from frappe.utils import get_gravatar, get_url from frappe.desk.form.load import get_meta_bundle from frappe.change_log import get_versions @@ -69,7 +69,7 @@ def get_bootinfo(): bootinfo['versions'] = {k: v['version'] for k, v in get_versions().items()} bootinfo.error_report_email = frappe.get_hooks("error_report_email") - bootinfo.default_background_image = "/assets/frappe/images/ui/into-the-dawn.jpg" + bootinfo.default_background_image = get_url("/assets/frappe/images/ui/into-the-dawn.jpg") return bootinfo diff --git a/frappe/public/css/font-awesome.css b/frappe/public/css/font-awesome.css index b2fef71aa8..dc282be73c 100644 --- a/frappe/public/css/font-awesome.css +++ b/frappe/public/css/font-awesome.css @@ -27,8 +27,8 @@ * -------------------------- */ @font-face { font-family: 'FontAwesome'; - src: url('../frappe/css/font/fontawesome-webfont.eot?v=3.2.1'); - src: url('../frappe/css/font/fontawesome-webfont.eot?#iefix&v=3.2.1') format('embedded-opentype'), url('../frappe/css/font/fontawesome-webfont.woff?v=3.2.1') format('woff'), url('../frappe/css/font/fontawesome-webfont.ttf?v=3.2.1') format('truetype'), url('../frappe/css/font/fontawesome-webfont.svg#fontawesomeregular?v=3.2.1') format('svg'); + src: url('/assets/frappe/css/font/fontawesome-webfont.eot?v=3.2.1'); + src: url('/assets/frappe/css/font/fontawesome-webfont.eot?#iefix&v=3.2.1') format('embedded-opentype'), url('/assets/frappe/css/font/fontawesome-webfont.woff?v=3.2.1') format('woff'), url('/assets/frappe/css/font/fontawesome-webfont.ttf?v=3.2.1') format('truetype'), url('/assets/frappe/css/font/fontawesome-webfont.svg#fontawesomeregular?v=3.2.1') format('svg'); font-weight: normal; font-style: normal; } @@ -36,7 +36,7 @@ @media screen and (-webkit-min-device-pixel-ratio:0) { @font-face { font-family: 'FontAwesome'; - src: url('../frappe/css/font/fontawesome-webfont.svg#fontawesomeregular?v=3.2.1') format('svg'); + src: url('/assets/frappe/css/font/fontawesome-webfont.svg#fontawesomeregular?v=3.2.1') format('svg'); } } diff --git a/frappe/public/js/frappe/assets.js b/frappe/public/js/frappe/assets.js index 59281d58f5..7340b19ae4 100644 --- a/frappe/public/js/frappe/assets.js +++ b/frappe/public/js/frappe/assets.js @@ -24,19 +24,17 @@ frappe.assets = { check: function() { // if version is different then clear localstorage if(window._version_number != localStorage.getItem("_version_number")) { - localStorage.clear(); + frappe.assets.clear_local_storage(); console.log("Cleared App Cache."); } if(localStorage._last_load) { var not_updated_since = new Date() - new Date(localStorage._last_load); if(not_updated_since < 10000 || not_updated_since > 86400000) { - localStorage.clear(); - console.log("Cleared localstorage"); + frappe.assets.clear_local_storage(); } } else { - localStorage.clear(); - console.log("Cleared localstorage"); + frappe.assets.clear_local_storage(); } frappe.assets.init_local_storage(); @@ -48,39 +46,44 @@ frappe.assets = { if(frappe.boot) localStorage.metadata_version = frappe.boot.metadata_version; }, - // check if the asset exists in - // localstorage - exists: function(src) { - if('localStorage' in window - && localStorage.getItem(src) && (frappe.boot ? !frappe.boot.developer_mode : true)) - return true; + clear_local_storage: function() { + $.each(["_last_load", "_version_number", "metadata_version", "page_info", + "last_visited"], function(i, key) { + localStorage.removeItem(key); + }); + + // clear assets + for(key in localStorage) { + if(key.indexOf("desk_assets:")===0 || key.indexOf("_page:")===0 + || key.indexOf("_doctype:")===0 || key.indexOf("preferred_breadcrumbs:")===0) { + localStorage.removeItem(key); + } + } + console.log("localStorage cleared"); }, - // add the asset to - // localstorage add: function(src, txt) { if('localStorage' in window) { try { - localStorage.setItem(src, txt); + frappe.assets.set(src, txt); } catch(e) { // if quota is exceeded, clear local storage and set item - localStorage.clear(); - console.log("Local Storage cleared"); - - localStorage.setItem(src, txt); + frappe.assets.clear_local_storage(); + frappe.assets.set(src, txt); } } }, - get: function(src) { - return localStorage.getItem(src); - }, - - extn: function(src) { - if(src.indexOf('?')!=-1) { - src = src.split('?').slice(-1)[0]; + // pass on to the handler to set + execute: function(src) { + if(!frappe.assets.exists(src)) { + frappe.assets.load(src); + } + var type = frappe.assets.extn(src); + if(frappe.assets.handler[type]) { + frappe.assets.handler[type](frappe.assets.get(src), src); + frappe.assets.executed_[src] = 1; } - return src.split('.').slice(-1)[0]; }, // load an asset via @@ -101,21 +104,29 @@ frappe.assets = { }) }, - // pass on to the handler to set - execute: function(src) { - if(!frappe.assets.exists(src)) { - frappe.assets.load(src); - } - var type = frappe.assets.extn(src); - if(frappe.assets.handler[type]) { - frappe.assets.handler[type](frappe.assets.get(src), src); - frappe.assets.executed_[src] = 1; - } + // check if the asset exists in + // localstorage + exists: function(src) { + if(frappe.assets.get(src) + && (frappe.boot ? !frappe.boot.developer_mode : true)) + return true; + }, + + get: function(src) { + return localStorage.getItem("desk_assets:" + src); + }, + + set: function(src, txt) { + localStorage.setItem("desk_assets:" + src, txt); + }, + + extn: function(src) { + if(src.indexOf('?')!=-1) { + src = src.split('?').slice(-1)[0]; + } + return src.split('.').slice(-1)[0]; }, - // handle types of assets - // and launch them in the - // app handler: { js: function(txt, src) { frappe.dom.eval(txt); diff --git a/frappe/public/js/frappe/desk.js b/frappe/public/js/frappe/desk.js index 9bc0094b01..96755ae8cd 100644 --- a/frappe/public/js/frappe/desk.js +++ b/frappe/public/js/frappe/desk.js @@ -1,10 +1,16 @@ // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // MIT License. See license.txt -$(document).ready(function() { +frappe.start_app = function() { + if(!frappe.Application) + return; frappe.assets.check(); frappe.provide('frappe.app'); $.extend(frappe.app, new frappe.Application()); +} + +$(document).ready(function() { + frappe.start_app(); }); frappe.Application = Class.extend({ @@ -23,9 +29,9 @@ frappe.Application = Class.extend({ this.set_rtl(); if(frappe.boot) { - if(localStorage.getItem("session_lost_route")) { - window.location.hash = localStorage.getItem("session_lost_route"); - localStorage.removeItem("session_lost_route"); + if(localStorage.getItem("session_last_route")) { + window.location.hash = localStorage.getItem("session_last_route"); + localStorage.removeItem("session_last_route"); } } @@ -78,8 +84,7 @@ frappe.Application = Class.extend({ check_metadata_cache_status: function() { if(frappe.boot.metadata_version != localStorage.metadata_version) { - localStorage.clear(); - console.log("Cleared Cache - New Metadata"); + frappe.assets.clear_local_storage(); frappe.assets.init_local_storage(); } }, diff --git a/frappe/public/js/frappe/request.js b/frappe/public/js/frappe/request.js index c752d594ec..f69f306c78 100644 --- a/frappe/public/js/frappe/request.js +++ b/frappe/public/js/frappe/request.js @@ -167,7 +167,7 @@ frappe.request.cleanup = function(opts, r) { // session expired? - Guest has no business here! if(r.session_expired || frappe.get_cookie("sid")==="Guest") { if(!frappe.app.logged_out) { - localStorage.setItem("session_lost_route", location.hash); + localStorage.setItem("session_last_route", location.hash); msgprint(__('Session Expired. Logging you out')); frappe.app.logout(); } diff --git a/frappe/public/js/frappe/ui/app_icon.js b/frappe/public/js/frappe/ui/app_icon.js index e99e1a5ee1..ef6234af79 100644 --- a/frappe/public/js/frappe/ui/app_icon.js +++ b/frappe/public/js/frappe/ui/app_icon.js @@ -12,9 +12,10 @@ frappe.ui.app_icon = { var module = modules[app] var icon = module.icon; var color = module.color; + console.log(frappe.urllib.get_full_url(icon)); if(icon.split(".").slice(-1)[0]==="svg") { $.ajax({ - url: icon, + url: frappe.urllib.get_full_url(icon), dataType: "text", async: false, success: function(data) { diff --git a/frappe/public/js/frappe/ui/toolbar/toolbar.js b/frappe/public/js/frappe/ui/toolbar/toolbar.js index d2e143fa9b..f20ef0882e 100644 --- a/frappe/public/js/frappe/ui/toolbar/toolbar.js +++ b/frappe/public/js/frappe/ui/toolbar/toolbar.js @@ -136,7 +136,7 @@ frappe.ui.toolbar.update_notifications = function() { } frappe.ui.toolbar.clear_cache = function() { - localStorage && localStorage.clear(); + frappe.assets.clear_local_storage(); $c('frappe.sessions.clear',{},function(r,rt){ if(!r.exc) { show_alert(r.message); diff --git a/frappe/public/js/frappe/views/breadcrumbs.js b/frappe/public/js/frappe/views/breadcrumbs.js index cb06f93e71..b9db4bdfe2 100644 --- a/frappe/public/js/frappe/views/breadcrumbs.js +++ b/frappe/public/js/frappe/views/breadcrumbs.js @@ -7,11 +7,11 @@ frappe.breadcrumbs = { preferred: {}, set_doctype_module: function(doctype, module) { - localStorage["preferred_breadcrumbs" + ":" + doctype] = module; + localStorage["preferred_breadcrumbs:" + doctype] = module; }, get_doctype_module: function(doctype) { - return localStorage["preferred_breadcrumbs" + ":" + doctype]; + return localStorage["preferred_breadcrumbs:" + doctype]; }, add: function(module, doctype, type) { diff --git a/frappe/public/js/legacy/dom.js b/frappe/public/js/legacy/dom.js index 268230c64e..616be9938f 100644 --- a/frappe/public/js/legacy/dom.js +++ b/frappe/public/js/legacy/dom.js @@ -180,9 +180,19 @@ frappe.urllib = { // returns the base url with http + domain + path (-index.cgi or # or ?) get_base_url: function() { - var url= window.location.href.split('#')[0].split('?')[0].split('desk')[0]; + var url= (frappe.base_url || window.location.href).split('#')[0].split('?')[0].split('desk')[0]; if(url.substr(url.length-1, 1)=='/') url = url.substr(0, url.length-1) return url + }, + + // returns absolute url + get_full_url: function(url) { + if(url.indexOf("http://")===0 || url.indexOf("https://")===0) { + return url; + } + return url.substr(0,1)==="/" ? + (frappe.urllib.get_base_url() + url) : + (frappe.urllib.get_base_url() + "/" + url); } } diff --git a/frappe/public/js/lib/jquery/bootstrap_theme/jquery-ui.selected.css b/frappe/public/js/lib/jquery/bootstrap_theme/jquery-ui.selected.css index 486f9891cc..e2b3936707 100644 --- a/frappe/public/js/lib/jquery/bootstrap_theme/jquery-ui.selected.css +++ b/frappe/public/js/lib/jquery/bootstrap_theme/jquery-ui.selected.css @@ -208,7 +208,7 @@ /*.ui-widget { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size:13px; }*/ .ui-widget .ui-widget { font-size: 1em; } /*.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1em; }*/ -/*.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(../frappe/js/lib/jquery/bootstrap_theme/images/ui-bg_glass_75_ffffff_1x400.png) 50% 50% repeat-x; color: #404040; }*/ +/*.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(/assets/frappe/js/lib/jquery/bootstrap_theme/images/ui-bg_glass_75_ffffff_1x400.png) 50% 50% repeat-x; color: #404040; }*/ .ui-widget-content { border: 1px solid #aaaaaa; background-color: #ffffff; color: #404040;} .ui-widget-content a { color: #404040; } .ui-widget-header { @@ -324,14 +324,14 @@ ----------------------------------*/ /* states and images */ -.ui-icon { width: 16px; height: 16px; background-image: url(../frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_222222_256x240.png); } -.ui-widget-content .ui-icon {background-image: url(../frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_222222_256x240.png); } -.ui-widget-header .ui-icon {background-image: url(../frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_222222_256x240.png); } -.ui-state-default .ui-icon { background-image: url(../frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_888888_256x240.png); } -.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(../frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_454545_256x240.png); } -.ui-state-active .ui-icon {background-image: url(../frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_454545_256x240.png); } -.ui-state-highlight .ui-icon {background-image: url(../frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_2e83ff_256x240.png); } -.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(../frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_f6cf3b_256x240.png); } +.ui-icon { width: 16px; height: 16px; background-image: url(/assets/frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(/assets/frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(/assets/frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(/assets/frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(/assets/frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(/assets/frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(/assets/frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(/assets/frappe/js/lib/jquery/bootstrap_theme/images/ui-icons_f6cf3b_256x240.png); } /* positioning */ .ui-icon-carat-1-n { background-position: 0 0; } diff --git a/frappe/templates/pages/desk.py b/frappe/templates/pages/desk.py index acab1ba9a3..ef295d017a 100644 --- a/frappe/templates/pages/desk.py +++ b/frappe/templates/pages/desk.py @@ -15,7 +15,6 @@ import frappe.sessions def get_context(context): if (frappe.session.user == "Guest" or 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() @@ -26,11 +25,36 @@ def get_context(context): boot_json = re.sub("\[^<]*\", "", boot_json) return { - "build_version": str(os.path.getmtime(os.path.join(frappe.local.sites_path, "assets", "js", - "desk.min.js"))), + "build_version": get_build_version(), "include_js": hooks["app_include_js"], "include_css": hooks["app_include_css"], - "boot": boot_json, + "boot": boot if context.get("for_mobile") else boot_json, "background_image": boot.user.background_image or boot.default_background_image, "google_analytics_id": frappe.conf.get("google_analytics_id") } + +@frappe.whitelist() +def get_desk_assets(build_version): + """Get desk assets to be loaded for mobile app""" + data = get_context({"for_mobile": True}) + assets = [{"type": "js", "data": ""}, {"type": "css", "data": ""}] + + if build_version != data["build_version"]: + # new build, send assets + for path in data["include_js"]: + with open(os.path.join(frappe.local.sites_path, path) ,"r") as f: + assets[0]["data"] = assets[0]["data"] + "\n" + unicode(f.read(), "utf-8") + + for path in data["include_css"]: + with open(os.path.join(frappe.local.sites_path, path) ,"r") as f: + assets[1]["data"] = assets[1]["data"] + "\n" + unicode(f.read(), "utf-8") + + return { + "build_version": data["build_version"], + "boot": data["boot"], + "assets": assets + } + +def get_build_version(): + return str(os.path.getmtime(os.path.join(frappe.local.sites_path, "assets", "js", + "desk.min.js"))) diff --git a/frappe/templates/styles/standard.css b/frappe/templates/styles/standard.css index f20cc7cd46..a2b9e0fb1a 100644 --- a/frappe/templates/styles/standard.css +++ b/frappe/templates/styles/standard.css @@ -1,5 +1,3 @@ -@import url(/assets/frappe/css/font/open-sans/open-sans.css); - @media screen { .print-format-gutter { background-color: #ddd;