diff --git a/.eslintrc b/.eslintrc index 46a4f4be8d..4b7dcf3457 100644 --- a/.eslintrc +++ b/.eslintrc @@ -120,6 +120,7 @@ "md5": true, "$": true, "jQuery": true, + "Vue": true, "moment": true, "hljs": true, "Awesomplete": true, diff --git a/cypress/integration/awesome_bar.js b/cypress/integration/awesome_bar.js index 44dbde8fcf..4b2ae0da93 100644 --- a/cypress/integration/awesome_bar.js +++ b/cypress/integration/awesome_bar.js @@ -8,13 +8,6 @@ context('Awesome Bar', () => { cy.get('.navbar-home').click(); }); - it('navigates to modules', () => { - cy.get('#navbar-search') - .type('modules{downarrow}{enter}', { delay: 100 }); - - cy.location('hash').should('eq', '#modules'); - }); - it('navigates to doctype list', () => { cy.get('#navbar-search') .type('todo{downarrow}{enter}', { delay: 100 }); diff --git a/frappe/boot.py b/frappe/boot.py index 18fb080d4f..043c1b0361 100644 --- a/frappe/boot.py +++ b/frappe/boot.py @@ -96,8 +96,8 @@ def load_conf_settings(bootinfo): if key in conf: bootinfo[key] = conf.get(key) def load_desktop_icons(bootinfo): - from frappe.desk.doctype.desktop_icon.desktop_icon import get_desktop_icons - bootinfo.desktop_icons = get_desktop_icons() + from frappe.config import get_modules_from_all_apps_for_user + bootinfo.allowed_modules = get_modules_from_all_apps_for_user() def get_allowed_pages(): return get_user_pages_or_reports('Page') diff --git a/frappe/config/__init__.py b/frappe/config/__init__.py index e69de29bb2..d26f788bba 100644 --- a/frappe/config/__init__.py +++ b/frappe/config/__init__.py @@ -0,0 +1,85 @@ +from __future__ import unicode_literals +from frappe import _ +import frappe +from frappe.desk.moduleview import get_data +from six import iteritems + +def get_modules_from_all_apps_for_user(user=None): + if not user: + user = frappe.session.user + + all_modules = get_modules_from_all_apps() + user_blocked_modules = frappe.get_doc('User', user).get_blocked_modules() + + allowed_modules_list = [m for m in all_modules if m.get("module_name") not in user_blocked_modules] + + return allowed_modules_list + +def get_modules_from_all_apps(): + modules_list = [] + for app in frappe.get_installed_apps(): + modules_list += get_modules_from_app(app) + return modules_list + +def get_modules_from_app(app): + try: + modules = frappe.get_attr(app + '.config.desktop.get_data')() or {} + except ImportError: + return [] + + # Only newly formatted modules that have a category to be shown on desk + modules = [m for m in modules if m.get("category")] + + active_domains = frappe.get_active_domains() + + if isinstance(modules, dict): + active_modules_list = [] + for m, module in iteritems(modules): + module['module_name'] = m + active_modules_list.append(module) + else: + active_modules_list = [] + for m in modules: + to_add = True + module_name = m.get("module_name") + + # Check Domain + if is_domain(m): + if module_name not in active_domains: + to_add = False + + if "condition" in m and not m["condition"]: + to_add = False + + if to_add: + onboard_present = is_onboard_present(m) if show_onboard(m) else False + m["onboard_present"] = onboard_present + active_modules_list.append(m) + + return active_modules_list + +def show_onboard(module): + return module.get("type") == "module" and module.get("category") in ["Modules", "Domains"] + +def is_onboard_present(module): + print(module["module_name"]) + exists_cache = {} + def exists(name, link_type): + exists = exists_cache.get(name) + if not exists: + if link_type == "doctype" and not frappe.db.get_value('DocType', name, 'issingle'): + exists = frappe.db.count(name) + else: + exists = True + exists_cache[name] = exists + return exists + + sections = get_data(module["module_name"], False) + for section in sections: + for item in section["items"]: + if exists(item.get("name"), item.get("type")): + return True + return False + +def is_domain(module): + return module.get("category") == "Domains" diff --git a/frappe/config/desk.py b/frappe/config/desk.py index 8efe293411..40db97ef8c 100644 --- a/frappe/config/desk.py +++ b/frappe/config/desk.py @@ -12,11 +12,7 @@ def get_data(): "name": "ToDo", "label": _("To Do"), "description": _("Documents assigned to you and by you."), - }, - { - "type": "doctype", - "name": "File", - "label": _("Files"), + "onboard": 1, }, { "type": "doctype", @@ -24,6 +20,18 @@ def get_data(): "label": _("Calendar"), "link": "List/Event/Calendar", "description": _("Event and other calendars."), + "onboard": 1, + }, + { + "type": "doctype", + "name": "Note", + "description": _("Private and public Notes."), + "onboard": 1, + }, + { + "type": "doctype", + "name": "File", + "label": _("Files"), }, { "type": "page", @@ -32,11 +40,6 @@ def get_data(): "description": _("Chat messages and other notifications."), "data_doctype": "Communication" }, - { - "type": "doctype", - "name": "Note", - "description": _("Private and public Notes."), - }, { "type": "page", "label": _("Activity"), @@ -52,6 +55,7 @@ def get_data(): "type": "doctype", "name": "Newsletter", "description": _("Newsletters to contacts, leads."), + "onboard": 1, }, { "type": "doctype", diff --git a/frappe/config/desktop.py b/frappe/config/desktop.py index b620508c06..d92f8469af 100644 --- a/frappe/config/desktop.py +++ b/frappe/config/desktop.py @@ -1,91 +1,87 @@ from __future__ import unicode_literals +import frappe from frappe import _ def get_data(): return [ + # Administration { "module_name": "Desk", + "category": "Administration", "label": _("Tools"), "color": "#FFF5A7", "reverse": 1, "icon": "octicon octicon-calendar", - "type": "module" - }, - { - "module_name": "File Manager", - "color": "#AA784D", - "doctype": "File", - "icon": "octicon octicon-file-directory", - "label": _("File Manager"), - "link": "List/File", - "type": "list", - "hidden": 1 - }, - { - "module_name": "Website", - "color": "#16a085", - "icon": "octicon octicon-globe", "type": "module", - "hidden": 1 + "description": "Todos, Notes and other basic tools to help you track your work." }, { - "module_name": "Integrations", - "color": "#16a085", - "icon": "octicon octicon-globe", - "type": "module", - "hidden": 1 - }, - { - "module_name": "Setup", + "module_name": "Settings", + "category": "Administration", + "label": _("Settings"), "color": "#bdc3c7", "reverse": 1, "icon": "octicon octicon-settings", "type": "module", - "hidden": 1 + "hidden": 1, + "description": "Configure your ERPNext account." }, { - "module_name": 'Email Inbox', - "type": 'list', - "label": 'Email Inbox', - "_label": _('Email Inbox'), - "_id": 'Email Inbox', - "_doctype": 'Communication', - "icon": 'fa fa-envelope-o', - "color": '#589494', - "link": 'List/Communication/Inbox' + "module_name": "Integrations", + "category": "Administration", + "label": _("Integrations"), + "color": "#16a085", + "icon": "octicon octicon-globe", + "type": "module", + "hidden": 1, + "description": "DropBox, Woocomerce, AWS, Shopify and GoCardless." + }, + { + "module_name": 'Contacts', + "category": "Administration", + "label": _("Contacts"), + "type": 'module', + "icon": "octicon octicon-book", + "color": '#ffaedb', + "hidden": 1, + "description": "People Contacts and Address Book." }, { "module_name": "Core", - "label": "Developer", + "category": "Administration", "_label": _("Developer"), + "label": "Developer", "color": "#589494", "icon": "octicon octicon-circuit-board", "type": "module", "system_manager": 1, - "hidden": 1 - }, - { - "module_name": 'Contacts', - "type": 'module', - "icon": "octicon octicon-book", - "color": '#FFAEDB', + "condition": getattr(frappe.local.conf, 'developer_mode', 0), "hidden": 1, + "description": "The Frappe innards of ERPNext. (Only active when developer mode is enabled)" + }, + + # Places + { + "module_name": "Website", + "category": "Places", + "label": _("Website"), + "_label": _("Website"), + "color": "#16a085", + "icon": "octicon octicon-globe", + "type": "module", + "hidden": 1, + "description": "Webpages and the Portal Side of Things." }, { "module_name": 'Social', + "category": "Places", "label": _('Social'), "icon": "octicon octicon-heart", "type": 'link', - "link": 'social/home', + "link": '#social/home', "color": '#FF4136', 'standard': 1, - 'idx': 15 + 'idx': 15, + "description": "Build your profile and share posts on the feed with other users." }, - { - "module_name": 'Settings', - "color": "#bdc3c7", - "reverse": 1, - "icon": "octicon octicon-settings", - "type": "module" - } ] diff --git a/frappe/config/settings.py b/frappe/config/settings.py deleted file mode 100644 index d1c00c2e71..0000000000 --- a/frappe/config/settings.py +++ /dev/null @@ -1,51 +0,0 @@ -from frappe import _ - -def get_data(): - return [{ - "label": _("Settings"), - "icon": "fa fa-wrench", - "items": [ - { - "type": "doctype", - "name": "System Settings", - "label": _("System Settings"), - "description": _("Language, Date and Time settings"), - "hide_count": True - }, - { - "type": "doctype", - "name": "Domain Settings", - "label": _("Domain Settings"), - "description": _("Enable / Disable Domains"), - "hide_count": True - }, - { - "type": "doctype", - "name": "Print Settings", - "label": _("Print Settings"), - "description": _("Print Style, PDF Size"), - "hide_count": True - }, - { - "type": "doctype", - "name": "Website Settings", - "label": _("Website Settings"), - "description": _("Landing Page, Website Theme, Brand Setup and more"), - "hide_count": True - }, - { - "type": "doctype", - "name": "S3 Backup Settings", - "label": _("S3 Backup Settings"), - "description": _("Enable / Disable Backup, Backup Frequency"), - "hide_count": True - }, - { - "type": "doctype", - "name": "SMS Settings", - "label": _("SMS Settings"), - "description": _("SMS Gateway URL, Message & Receiver Parameter"), - "hide_count": True - } - ] - }] diff --git a/frappe/config/website.py b/frappe/config/website.py index de66ca0959..2de27a581b 100644 --- a/frappe/config/website.py +++ b/frappe/config/website.py @@ -11,11 +11,13 @@ def get_data(): "type": "doctype", "name": "Web Page", "description": _("Content web page."), + "onboard": 1, }, { "type": "doctype", "name": "Web Form", "description": _("User editable form on Website."), + "onboard": 1, }, { "type": "doctype", @@ -35,6 +37,7 @@ def get_data(): "type": "doctype", "name": "Blog Post", "description": _("Single Post (article)."), + "onboard": 1, }, { "type": "doctype", @@ -56,11 +59,13 @@ def get_data(): "type": "doctype", "name": "Website Settings", "description": _("Setup of top navigation bar, footer and logo."), + "onboard": 1, }, { "type": "doctype", "name": "Website Theme", "description": _("List of themes for Website."), + "onboard": 1, }, { "type": "doctype", @@ -86,6 +91,7 @@ def get_data(): "type": "doctype", "name": "Portal Settings", "label": _("Portal Settings"), + "onboard": 1, } ] }, diff --git a/frappe/core/doctype/domain/domain.py b/frappe/core/doctype/domain/domain.py index ea21e73b95..a4e9f503ab 100644 --- a/frappe/core/doctype/domain/domain.py +++ b/frappe/core/doctype/domain/domain.py @@ -18,8 +18,7 @@ class Domain(Document): self.setup_roles() self.setup_properties() self.set_values() - # always set the desktop icons while changing the domain settings - self.setup_desktop_icons() + if not int(frappe.defaults.get_defaults().setup_complete or 0): # if setup not complete, setup desktop etc. self.setup_sidebar_items() @@ -89,12 +88,6 @@ class Domain(Document): frappe.db.set_value('Portal Settings', None, 'default_role', self.data.get('default_portal_role')) - def setup_desktop_icons(self): - '''set desktop icons form `data.desktop_icons`''' - from frappe.desk.doctype.desktop_icon.desktop_icon import set_desktop_icons - if self.data.desktop_icons: - set_desktop_icons(self.data.desktop_icons) - def setup_properties(self): if self.data.properties: for args in self.data.properties: diff --git a/frappe/core/doctype/user/user.js b/frappe/core/doctype/user/user.js index 71d7cfc0e8..d334731015 100644 --- a/frappe/core/doctype/user/user.js +++ b/frappe/core/doctype/user/user.js @@ -71,10 +71,6 @@ frappe.ui.form.on('User', { frm.toggle_display(['sb1', 'sb3', 'modules_access'], false); if(!frm.is_new()) { - frm.add_custom_button(__("Set Desktop Icons"), function() { - frappe.frappe_toolbar.modules_select.show(doc.name); - }, null, "btn-default") - if(has_access_to_edit_user()) { frm.add_custom_button(__("Set User Permissions"), function() { diff --git a/frappe/core/doctype/user/user.json b/frappe/core/doctype/user/user.json index 4fcee60dc5..6d429f3248 100644 --- a/frappe/core/doctype/user/user.json +++ b/frappe/core/doctype/user/user.json @@ -1511,7 +1511,7 @@ "columns": 0, "default": "", "description": "", - "fieldname": "desktop_icon_access", + "fieldname": "sb_allow_modules", "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, @@ -1520,7 +1520,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Allow Desktop Icon", + "label": "Allow Modules", "length": 0, "no_copy": 0, "permlevel": 1, @@ -2303,7 +2303,7 @@ "issingle": 0, "istable": 0, "max_attachments": 5, - "modified": "2018-11-21 12:34:57.652854", + "modified": "2019-01-30 13:56:10.732154", "modified_by": "Administrator", "module": "Core", "name": "User", diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index dbc2ccd873..087d7c9d21 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -36,9 +36,9 @@ class User(Document): self.name = self.email def onload(self): + from frappe.config import get_modules_from_all_apps self.set_onload('all_modules', - [m.module_name for m in frappe.db.get_all('Desktop Icon', - fields=['module_name'], filters={'standard': 1}, order_by="module_name")]) + [m.get("module_name") for m in get_modules_from_all_apps()]) def before_insert(self): self.flags.in_insert = True diff --git a/frappe/core/page/desktop/README.md b/frappe/core/page/desktop/README.md deleted file mode 100644 index 4ac65f50b5..0000000000 --- a/frappe/core/page/desktop/README.md +++ /dev/null @@ -1 +0,0 @@ -First screen after login. Array of module icons based on permission. \ No newline at end of file diff --git a/frappe/core/page/desktop/__init__.py b/frappe/core/page/desktop/__init__.py index 0e57cb68c3..e69de29bb2 100644 --- a/frappe/core/page/desktop/__init__.py +++ b/frappe/core/page/desktop/__init__.py @@ -1,3 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - diff --git a/frappe/core/page/desktop/all_applications_dialog.html b/frappe/core/page/desktop/all_applications_dialog.html deleted file mode 100644 index d26152c84b..0000000000 --- a/frappe/core/page/desktop/all_applications_dialog.html +++ /dev/null @@ -1,26 +0,0 @@ -
-
-{% if (frappe.user.has_role("System Manager")) { %} -

Install new applications -

-{% } %} -
-

{%= __("Checked items will be shown on desktop") %}

-
- {% for(var i=0, l=all_modules.length; i < l; i++) { - var module_name = all_modules[i]; - var module = frappe.get_module(module_name); - if (desktop_items.indexOf(module_name)===-1 - || frappe.user.is_module_blocked(module_name)) { continue; } - %} -
-
- -
-
- {% } %} -
diff --git a/frappe/core/page/desktop/desktop.js b/frappe/core/page/desktop/desktop.js index 24dd0c3b4e..13b64c9246 100644 --- a/frappe/core/page/desktop/desktop.js +++ b/frappe/core/page/desktop/desktop.js @@ -1,344 +1 @@ -frappe.provide('frappe.desktop'); - -frappe.pages['desktop'].on_page_load = function(wrapper) { - - // load desktop - if(!frappe.list_desktop) { - frappe.desktop.set_background(); - } - frappe.desktop.refresh(wrapper); -}; - -frappe.pages['desktop'].on_page_show = function(wrapper) { - if(frappe.list_desktop) { - $("body").attr("data-route", "list-desktop"); - } -}; - -$.extend(frappe.desktop, { - refresh: function(wrapper) { - if (wrapper) { - this.wrapper = $(wrapper); - } - - this.render(); - this.make_sortable(); - }, - - render: function() { - var me = this; - frappe.utils.set_title(__("Desktop")); - - var template = frappe.list_desktop ? "desktop_list_view" : "desktop_icon_grid"; - - var all_icons = frappe.get_desktop_icons(); - var explore_icon = { - module_name: 'Explore', - label: 'Explore', - _label: __('Explore'), - _id: 'Explore', - _doctype: '', - icon: 'octicon octicon-telescope', - color: '#7578f6', - link: 'modules' - }; - explore_icon.app_icon = frappe.ui.app_icon.get_html(explore_icon); - all_icons.push(explore_icon); - - frappe.desktop.wrapper.html(frappe.render_template(template, { - // all visible icons - desktop_items: all_icons, - })); - - frappe.desktop.setup_module_click(); - - // notifications - frappe.desktop.show_pending_notifications(); - $(document).on("notification-update", function() { - me.show_pending_notifications(); - }); - - $(document).trigger("desktop-render"); - - }, - - render_help_messages: function(help_messages) { - var wrapper = frappe.desktop.wrapper.find('.help-message-wrapper'); - var $help_messages = wrapper.find('.help-messages'); - - var set_current_message = function(idx) { - idx = cint(idx); - wrapper.current_message_idx = idx; - wrapper.find('.left-arrow, .right-arrow').addClass('disabled'); - wrapper.find('.help-message-item').addClass('hidden'); - wrapper.find('[data-message-idx="'+idx+'"]').removeClass('hidden'); - if(idx > 0) { - wrapper.find('.left-arrow').removeClass('disabled'); - } - if(idx < help_messages.length - 1) { - wrapper.find('.right-arrow').removeClass('disabled'); - } - } - - if(help_messages) { - wrapper.removeClass('hidden'); - help_messages.forEach(function(message, i) { - var $message = $('') - .attr('data-message-idx', i) - .html(frappe.render_template('desktop_help_message', message)) - .appendTo($help_messages); - - }); - - set_current_message(0); - - wrapper.find('.close').on('click', function() { - wrapper.addClass('hidden'); - }); - } - - wrapper.find('.left-arrow').on('click', function() { - if(wrapper.current_message_idx) { - set_current_message(wrapper.current_message_idx - 1); - } - }) - - wrapper.find('.right-arrow').on('click', function() { - if(help_messages.length > wrapper.current_message_idx + 1) { - set_current_message(wrapper.current_message_idx + 1); - } - }); - - }, - - setup_module_click: function() { - frappe.desktop.wiggling = false; - - if(frappe.list_desktop) { - frappe.desktop.wrapper.on("click", ".desktop-list-item", function() { - frappe.desktop.open_module($(this)); - }); - } else { - frappe.desktop.wrapper.on("click", ".app-icon, .app-icon-svg", function() { - if ( !frappe.desktop.wiggling ) { - frappe.desktop.open_module($(this).parent()); - } - }); - } - frappe.desktop.wrapper.on("click", ".circle", function() { - var doctype = $(this).attr('data-doctype'); - if(doctype) { - frappe.ui.notifications.show_open_count_list(doctype); - } - }); - - frappe.desktop.setup_wiggle(); - }, - - setup_wiggle: () => { - // Wiggle, Wiggle, Wiggle. - const DURATION_LONG_PRESS = 1000; - - var timer_id = 0; - const $cases = frappe.desktop.wrapper.find('.case-wrapper'); - const $icons = frappe.desktop.wrapper.find('.app-icon'); - const $notis = $(frappe.desktop.wrapper.find('.circle').toArray().filter((object) => { - // This hack is so bad, I should punch myself. - // Seriously, punch yourself. - const text = $(object).find('.circle-text').html(); - - return text; - })); - - const clearWiggle = () => { - const $closes = $cases.find('.module-remove'); - $closes.hide(); - $notis.show(); - - $icons.removeClass('wiggle'); - - frappe.desktop.wiggling = false; - }; - - frappe.desktop.wrapper.on('mousedown', '.app-icon', () => { - timer_id = setTimeout(() => { - frappe.desktop.wiggling = true; - // hide all notifications. - $notis.hide(); - - $cases.each((i) => { - const $case = $($cases[i]); - const template = - ` -
-
- - × - -
-
- `; - - $case.append(template); - const $close = $case.find('.module-remove'); - const name = $case.attr('title'); - $close.click(() => { - // good enough to create dynamic dialogs? - const dialog = new frappe.ui.Dialog({ - title: __(`Hide ${name}?`) - }); - dialog.set_primary_action(__('Hide'), () => { - frappe.call({ - method: 'frappe.desk.doctype.desktop_icon.desktop_icon.hide', - args: { name: name }, - freeze: true, - callback: (response) => - { - if ( response.message ) { - location.reload(); - } - } - }) - - dialog.hide(); - - clearWiggle(); - }); - // Hacks, Hacks and Hacks. - var $cancel = dialog.get_close_btn(); - $cancel.click(() => { - clearWiggle(); - }); - $cancel.html(__(`Cancel`)); - - dialog.show(); - }); - }); - - $icons.addClass('wiggle'); - - }, DURATION_LONG_PRESS); - }); - frappe.desktop.wrapper.on('mouseup mouseleave', '.app-icon', () => { - clearTimeout(timer_id); - }); - - // also stop wiggling if clicked elsewhere. - $('body').click((event) => { - if ( frappe.desktop.wiggling ) { - const $target = $(event.target); - // our target shouldn't be .app-icons or .close - const $parent = $target.parents('.case-wrapper'); - if ( $parent.length == 0 ) - clearWiggle(); - } - }); - // end wiggle - }, - - open_module: function(parent) { - var link = parent.attr("data-link"); - if(link) { - if(link.indexOf('javascript:')===0) { - eval(link.substr(11)); - } else if(link.substr(0, 1)==="/" || link.substr(0, 4)==="http") { - window.open(link, "_blank"); - } else { - frappe.set_route(link); - } - return false; - } else { - var module = frappe.get_module(parent.attr("data-name")); - if (module && module.onclick) { - module.onclick(); - return false; - } - } - }, - - make_sortable: function() { - if (frappe.dom.is_touchscreen() || frappe.list_desktop) { - return; - } - - new Sortable($("#icon-grid").get(0), { - animation: 150, - onUpdate: function(event) { - var new_order = []; - $("#icon-grid .case-wrapper").each(function(i, e) { - new_order.push($(this).attr("data-name")); - }); - - frappe.call({ - method: 'frappe.desk.doctype.desktop_icon.desktop_icon.set_order', - args: { - 'new_order': new_order, - 'user': frappe.session.user - }, - quiet: true - }); - } - }); - }, - - set_background: function() { - frappe.ui.set_user_background(frappe.boot.user.background_image, null, - frappe.boot.user.background_style); - }, - - show_pending_notifications: function() { - var modules_list = frappe.get_desktop_icons(); - for (var i=0, l=modules_list.length; i < l; i++) { - var module = modules_list[i]; - - var module_doctypes = frappe.boot.notification_info.module_doctypes[module.module_name]; - - var sum = 0; - - if(module_doctypes && frappe.boot.notification_info.open_count_doctype) { - // sum all doctypes for a module - for (var j=0, k=module_doctypes.length; j < k; j++) { - var doctype = module_doctypes[j]; - let count = (frappe.boot.notification_info.open_count_doctype[doctype] || 0); - count = typeof count == "string" ? parseInt(count) : count; - sum += count; - } - } - - if(frappe.boot.notification_info.open_count_doctype - && frappe.boot.notification_info.open_count_doctype[module.module_name]!=null) { - // notification count explicitly for doctype - let count = frappe.boot.notification_info.open_count_doctype[module.module_name] || 0; - count = typeof count == "string" ? parseInt(count) : count; - sum += count; - } - - if(frappe.boot.notification_info.open_count_module - && frappe.boot.notification_info.open_count_module[module.module_name]!=null) { - // notification count explicitly for module - let count = frappe.boot.notification_info.open_count_module[module.module_name] || 0; - count = typeof count == "string" ? parseInt(count) : count; - sum += count; - } - - // if module found - if(module._id.indexOf('/')===-1 && !module._report) { - var notifier = $(".module-count-" + frappe.scrub(module._id)); - if(notifier.length) { - notifier.toggle(sum ? true : false); - var circle = notifier.find(".circle-text"); - var text = sum || ''; - if(text > 99) { - text = '99+'; - } - - if(circle.length) { - circle.html(text); - } else { - notifier.html(text); - } - } - } - } - } -}); +frappe.pages['desktop'].on_page_load = function() {}; \ No newline at end of file diff --git a/frappe/core/page/desktop/desktop.json b/frappe/core/page/desktop/desktop.json index 6255e3e6fe..66bbfbfd40 100644 --- a/frappe/core/page/desktop/desktop.json +++ b/frappe/core/page/desktop/desktop.json @@ -1,10 +1,11 @@ { - "creation": "2013-02-14 17:37:37.000000", + "content": null, + "creation": "2019-01-29 13:11:48.872579", "docstatus": 0, "doctype": "Page", - "icon": "fa fa-th", - "idx": 1, - "modified": "2013-07-11 14:41:56.000000", + "icon": "icon-th", + "idx": 0, + "modified": "2019-01-29 13:11:48.872579", "modified_by": "Administrator", "module": "Core", "name": "desktop", @@ -15,6 +16,9 @@ "role": "All" } ], + "script": null, "standard": "Yes", + "style": null, + "system_page": 0, "title": "Desktop" } \ No newline at end of file diff --git a/frappe/core/page/desktop/desktop.py b/frappe/core/page/desktop/desktop.py deleted file mode 100644 index f426a67979..0000000000 --- a/frappe/core/page/desktop/desktop.py +++ /dev/null @@ -1,25 +0,0 @@ -from __future__ import unicode_literals - -import functools -import frappe -from past.builtins import cmp - -@frappe.whitelist() -def get_help_messages(): - '''Return help messages for the desktop (called via `get_help_messages` hook) - - Format for message: - - { - title: _('Add Employees to Manage Them'), - description: _('Add your Employees so you can manage leaves, expenses and payroll'), - action: 'Add Employee', - route: 'List/Employee' - } - - ''' - messages = [] - for fn in frappe.get_hooks('get_help_messages'): - messages += frappe.get_attr(fn)() - - return sorted(messages, key = functools.cmp_to_key(lambda a, b: cmp(a.get('count'), b.get('count')))) diff --git a/frappe/core/page/desktop/desktop_help_message.html b/frappe/core/page/desktop/desktop_help_message.html deleted file mode 100644 index 7de47abf03..0000000000 --- a/frappe/core/page/desktop/desktop_help_message.html +++ /dev/null @@ -1,8 +0,0 @@ -
{{ title }}
-

{{ description }}

-
- {{ action }} - - - -
\ No newline at end of file diff --git a/frappe/core/page/desktop/desktop_icon_grid.html b/frappe/core/page/desktop/desktop_icon_grid.html deleted file mode 100644 index 6b85c8a56e..0000000000 --- a/frappe/core/page/desktop/desktop_icon_grid.html +++ /dev/null @@ -1,21 +0,0 @@ -
-
- {% for (var i=0, l=desktop_items.length; i < l; i++) { %} - {{ frappe.render_template("desktop_module_icon", desktop_items[i]) }} - {% } %} -
- -
-
diff --git a/frappe/core/page/desktop/desktop_list_view.html b/frappe/core/page/desktop/desktop_list_view.html deleted file mode 100644 index d3dd514076..0000000000 --- a/frappe/core/page/desktop/desktop_list_view.html +++ /dev/null @@ -1,23 +0,0 @@ -
-
-
-
- {% for (var i=0, l=desktop_items.length; i < l; i++) { - var module = desktop_items[i]; - %} -
-

- - {{ module._label }} -

- -
- {% } %} -
-
-
-
diff --git a/frappe/core/page/desktop/desktop_module_icon.html b/frappe/core/page/desktop/desktop_module_icon.html deleted file mode 100644 index 3e9a451eec..0000000000 --- a/frappe/core/page/desktop/desktop_module_icon.html +++ /dev/null @@ -1,11 +0,0 @@ -
- {{ app_icon }} -
- - - {{ _label }} -
-
diff --git a/frappe/desk/doctype/desktop_icon/desktop_icon.json b/frappe/desk/doctype/desktop_icon/desktop_icon.json index ee9765e944..59c95953ad 100644 --- a/frappe/desk/doctype/desktop_icon/desktop_icon.json +++ b/frappe/desk/doctype/desktop_icon/desktop_icon.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, @@ -14,6 +15,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -40,10 +42,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -70,10 +74,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -100,10 +106,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -130,10 +138,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -159,10 +169,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -189,10 +201,76 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "description", + "fieldtype": "Small Text", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Description", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "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, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "category", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Category", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "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, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -219,10 +297,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -249,10 +329,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -279,10 +361,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -308,10 +392,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -339,10 +425,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -370,10 +458,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -401,10 +491,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -431,10 +523,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -460,10 +554,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -490,10 +586,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -520,10 +618,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -550,10 +650,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -580,6 +682,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 } ], @@ -593,7 +696,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-05-08 15:41:31.121652", + "modified": "2019-01-24 04:58:58.720618", "modified_by": "Administrator", "module": "Desk", "name": "Desktop Icon", @@ -602,7 +705,6 @@ "permissions": [ { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, @@ -629,5 +731,6 @@ "sort_order": "DESC", "title_field": "module_name", "track_changes": 1, - "track_seen": 0 + "track_seen": 0, + "track_views": 0 } \ No newline at end of file diff --git a/frappe/desk/doctype/desktop_icon/desktop_icon.py b/frappe/desk/doctype/desktop_icon/desktop_icon.py index 175d1ece7d..fcf10ef61d 100644 --- a/frappe/desk/doctype/desktop_icon/desktop_icon.py +++ b/frappe/desk/doctype/desktop_icon/desktop_icon.py @@ -31,7 +31,7 @@ def get_desktop_icons(user=None): user_icons = frappe.cache().hget('desktop_icons', user) if not user_icons: - fields = ['module_name', 'hidden', 'label', 'link', 'type', 'icon', 'color', + fields = ['module_name', 'hidden', 'label', 'link', 'type', 'icon', 'color', 'description', 'category', '_doctype', '_report', 'idx', 'force_show', 'reverse', 'custom', 'standard', 'blocked'] active_domains = frappe.get_active_domains() diff --git a/frappe/desk/moduleview.py b/frappe/desk/moduleview.py index f5a1e47bf4..b90d6584a5 100644 --- a/frappe/desk/moduleview.py +++ b/frappe/desk/moduleview.py @@ -24,7 +24,7 @@ def hide_module(module): set_hidden(module, frappe.session.user, 1) clear_desktop_icons_cache() -def get_data(module): +def get_data(module, build=True): """Get module data for the module view `desk/#Module/[name]`""" doctype_info = get_doctype_info(module) data = build_config_from_file(module) @@ -42,6 +42,43 @@ def get_data(module): #set_last_modified(data) + + if build: + exists_cache = {} + def exists(name): + exists = exists_cache.get(name) + if not exists: + if not frappe.db.get_value('DocType', name, 'issingle'): + exists = frappe.db.count(name) + else: + exists = True + exists_cache[name] = exists + return exists + + for section in data: + for item in section["items"]: + # Onboarding + + # First disable based on exists of depends_on list + doctype = item.get("doctype") + dependencies = item.get("dependencies") or None + if not dependencies and doctype: + item["dependencies"] = [doctype] + + dependencies = item.get("dependencies") + if dependencies: + incomplete_dependencies = [d for d in dependencies if not exists(d)] + if len(incomplete_dependencies): + item["incomplete_dependencies"] = incomplete_dependencies + + if item.get("onboard"): + # Mark Spotlights for initial + if item.get("type") == "doctype": + name = item.get("name") + count = exists(name) + + item["count"] = count + return data def build_config_from_file(module): diff --git a/frappe/desk/page/modules/__init__.py b/frappe/desk/page/modules/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/desk/page/modules/modules.js b/frappe/desk/page/modules/modules.js deleted file mode 100644 index 80048fbf59..0000000000 --- a/frappe/desk/page/modules/modules.js +++ /dev/null @@ -1,185 +0,0 @@ -frappe.pages['modules'].on_page_load = function(wrapper) { - var page = frappe.ui.make_app_page({ - parent: wrapper, - title: 'Modules', - single_column: false - }); - - frappe.modules_page = page; - frappe.module_links = {}; - page.section_data = {}; - - page.wrapper.find('.page-head h1').css({'padding-left': '15px'}); - // page.wrapper.find('.page-content').css({'margin-top': '0px'}); - - // menu - page.add_menu_item(__('Set Desktop Icons'), function() { - frappe.frappe_toolbar.modules_select - .show(frappe.session.user); - }); - - if(frappe.user.has_role('System Manager')) { - page.add_menu_item(__('Install Apps'), function() { - frappe.set_route("applications"); - }); - } - - page.get_page_modules = () => { - return frappe.get_desktop_icons(true) - .filter(d => d.type==='module' && !d.blocked) - .sort((a, b) => { return (a._label > b._label) ? 1 : -1; }); - }; - - let get_module_sidebar_item = (item) => `
  • - - - ${item._label} - -
  • `; - - let get_sidebar_html = () => { - let sidebar_items_html = page.get_page_modules() - .map(get_module_sidebar_item.bind(this)).join(""); - - return ``; - }; - - // render sidebar - page.sidebar.html(get_sidebar_html()); - - // help click - page.main.on("click", '.module-section-link[data-type="help"]', function() { - frappe.help.show_video($(this).attr("data-youtube-id")); - return false; - }); - - // notifications click - page.main.on("click", '.open-notification', function() { - var doctype = $(this).attr('data-doctype'); - if(doctype) { - frappe.ui.notifications.show_open_count_list(doctype); - } - }); - - page.activate_link = function(link) { - page.last_link = link; - page.wrapper.find('.module-sidebar-item.active, .module-link.active').removeClass('active'); - $(link).addClass('active').parent().addClass("active"); - show_section($(link).attr('data-name')); - }; - - var show_section = function(module_name) { - if (!module_name) return; - if(module_name in page.section_data) { - render_section(page.section_data[module_name]); - } else { - page.main.empty(); - return frappe.call({ - method: "frappe.desk.moduleview.get", - args: { - module: module_name - }, - callback: function(r) { - var m = frappe.get_module(module_name); - m.data = r.message.data; - process_data(module_name, m.data); - page.section_data[module_name] = m; - render_section(m); - }, - freeze: true, - }); - } - - }; - - var render_section = function(m) { - page.set_title(__(m.label)); - page.main.html(frappe.render_template('modules_section', m)); - - // if(frappe.utils.is_xs() || frappe.utils.is_sm()) { - // // call this after a timeout, becuase a refresh will set the page to the top - // setTimeout(function() { - // $(document).scrollTop($('.module-body').offset().top - 150); - // }, 100); - // } - - //setup_section_toggle(); - frappe.app.update_notification_count_in_modules(); - }; - - var process_data = function(module_name, data) { - frappe.module_links[module_name] = []; - data.forEach(function(section) { - section.items.forEach(function(item) { - item.style = ''; - if(item.type==="doctype") { - item.doctype = item.name; - - // map of doctypes that belong to a module - frappe.module_links[module_name].push(item.name); - } - if(!item.route) { - if(item.link) { - item.route=strip(item.link, "#"); - } - else if(item.type==="doctype") { - if(frappe.model.is_single(item.doctype)) { - item.route = 'Form/' + item.doctype; - } else { - if (item.filters) { - frappe.route_options=item.filters; - } - item.route="List/" + item.doctype; - //item.style = 'font-weight: 500;'; - } - // item.style = 'font-weight: bold;'; - } - else if(item.type==="report" && item.is_query_report) { - item.route="query-report/" + item.name; - } - else if(item.type==="report") { - item.route="List/" + item.doctype + "/Report/" + item.name; - } - else if(item.type==="page") { - item.route=item.name; - } - } - - if(item.route_options) { - item.route += "?" + $.map(item.route_options, function(value, key) { - return encodeURIComponent(key) + "=" + encodeURIComponent(value); }).join('&'); - } - - if(item.type==="page" || item.type==="help" || item.type==="report" || - (item.doctype && frappe.model.can_read(item.doctype))) { - item.shown = true; - } - }); - }); - }; -}; - -frappe.pages['modules'].on_page_show = function(wrapper) { - let route = frappe.get_route(); - let modules = frappe.modules_page.get_page_modules().map(d => d.module_name); - $("body").attr("data-sidebar", 1); - if(route.length > 1) { - // activate section based on route - let module_name = route[1]; - if(modules.includes(module_name)) { - frappe.modules_page.activate_link( - frappe.modules_page.sidebar.find('.module-link[data-name="'+ module_name +'"]')); - } else { - frappe.throw(__(`Module ${module_name} not found.`)); - } - } else if(frappe.modules_page.last_link) { - // open last link - frappe.set_route('modules', frappe.modules_page.last_link.attr('data-name')); - } else { - // first time, open the first page - frappe.modules_page.activate_link(frappe.modules_page.sidebar.find('.module-link:first')); - } -}; diff --git a/frappe/desk/page/modules/modules.json b/frappe/desk/page/modules/modules.json deleted file mode 100644 index 1858a921b2..0000000000 --- a/frappe/desk/page/modules/modules.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "content": null, - "creation": "2016-03-07 04:46:00.420330", - "docstatus": 0, - "doctype": "Page", - "idx": 0, - "modified": "2016-03-07 04:46:00.420330", - "modified_by": "Administrator", - "module": "Desk", - "name": "modules", - "owner": "Administrator", - "page_name": "modules", - "roles": [], - "script": null, - "standard": "Yes", - "style": null, - "title": "Modules" -} \ No newline at end of file diff --git a/frappe/desk/page/modules/modules_section.html b/frappe/desk/page/modules/modules_section.html deleted file mode 100644 index 5d23db795a..0000000000 --- a/frappe/desk/page/modules/modules_section.html +++ /dev/null @@ -1,30 +0,0 @@ -
    -{% for (var i=0; i < data.length; i++) { var section = data[i]; %} -{% if ((i % 2)===0) { %}
    {% } %} -
    -
    - {{ section.label }} -
    -
    - {% for (var j=0; j < section.items.length; j++) { - var item = section.items[j]; - if(item.shown) { %} -
    - - {{ item.label || __(item.name) }} - - {% if(item.type==="doctype") { %} - - {% } %} -
    - {% } %} - {% } %} -
    -
    -{% if ((i % 2)===1 || i===data.length-1) { %}
    {% } %} -{% } %} -
    diff --git a/frappe/installer.py b/frappe/installer.py index c4af23976f..792d8580e8 100755 --- a/frappe/installer.py +++ b/frappe/installer.py @@ -23,7 +23,7 @@ from frappe.database import setup_database def install_db(root_login="root", root_password=None, db_name=None, source_sql=None, admin_password=None, verbose=True, force=0, site_config=None, reinstall=False, db_type=None): - + if not db_type: db_type = frappe.conf.db_type or 'mariadb' @@ -158,9 +158,6 @@ def remove_app(app_name, dry_run=False, yes=False): if not dry_run: frappe.delete_doc("Module Def", module_name) - # delete desktop icons - frappe.db.sql('delete from `tabDesktop Icon` where app=%s', app_name) - remove_from_installed_apps(app_name) if not dry_run: diff --git a/frappe/patches.txt b/frappe/patches.txt index c8623b78de..21f09f6f0f 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -145,11 +145,9 @@ frappe.patches.v6_16.feed_doc_owner frappe.patches.v6_21.print_settings_repeat_header_footer frappe.patches.v6_24.set_language_as_code frappe.patches.v6_20x.update_insert_after -finally:frappe.patches.v6_24.sync_desktop_icons frappe.patches.v6_20x.set_allow_draft_for_print frappe.patches.v6_20x.remove_roles_from_website_user frappe.patches.v7_0.set_user_fullname -frappe.patches.v7_0.desktop_icons_hidden_by_admin_as_blocked frappe.patches.v7_0.add_communication_in_doc frappe.patches.v7_0.update_send_after_in_bulk_email execute:frappe.db.sql('''delete from `tabSingles` where doctype="Email Settings"''') # 2016-06-13 @@ -183,15 +181,11 @@ frappe.patches.v8_0.deprecate_integration_broker frappe.patches.v8_0.update_gender_and_salutation frappe.patches.v8_0.setup_email_inbox #2017-03-29 frappe.patches.v8_0.newsletter_childtable_migrate -execute:frappe.db.sql("delete from `tabDesktop Icon` where module_name='Communication'") -execute:frappe.db.sql("update `tabDesktop Icon` set type='list' where _doctype='Communication'") -frappe.patches.v8_0.fix_non_english_desktop_icons # 2017-04-12 frappe.patches.v8_0.set_doctype_values_in_custom_role frappe.patches.v8_0.install_new_build_system_requirements frappe.patches.v8_0.set_currency_field_precision # 2017-05-09 frappe.patches.v8_0.rename_print_to_printing frappe.patches.v7_1.disabled_print_settings_for_custom_print_format -frappe.patches.v8_0.update_desktop_icons execute:frappe.db.sql('update tabReport set module="Desk" where name="ToDo"') frappe.patches.v8_1.enable_allow_error_traceback_in_system_settings frappe.patches.v8_1.update_format_options_in_auto_email_report @@ -236,3 +230,4 @@ frappe.patches.v11_0.fix_order_by_in_reports_json execute:frappe.delete_doc('Page', 'applications', ignore_missing=True) frappe.patches.v11_0.set_missing_creation_and_modified_value_for_user_permissions frappe.patches.v12_0.set_primary_key_in_series +execute:frappe.delete_doc("Page", "modules", ignore_missing=True) diff --git a/frappe/patches/v6_24/sync_desktop_icons.py b/frappe/patches/v6_24/sync_desktop_icons.py deleted file mode 100644 index 74f52e6056..0000000000 --- a/frappe/patches/v6_24/sync_desktop_icons.py +++ /dev/null @@ -1,44 +0,0 @@ -from __future__ import unicode_literals -import frappe, json - -from frappe.desk.doctype.desktop_icon.desktop_icon import sync_from_app, get_user_copy -import frappe.defaults - -def execute(): - frappe.reload_doc('desk', 'doctype', 'desktop_icon') - - frappe.db.sql('delete from `tabDesktop Icon`') - - modules_list = [] - for app in frappe.get_installed_apps(): - modules_list += sync_from_app(app) - - # sync hidden modules - hidden_modules = frappe.db.get_global('hidden_modules') - if hidden_modules: - for m in json.loads(hidden_modules): - try: - desktop_icon = frappe.get_doc('Desktop Icon', {'module_name': m, 'standard': 1, 'app': app}) - desktop_icon.db_set('hidden', 1) - except frappe.DoesNotExistError: - pass - - # sync user sort - for user in frappe.get_all('User', filters={'user_type': 'System User'}): - user_list = frappe.defaults.get_user_default('_user_desktop_items', user=user.name) - if user_list: - user_list = json.loads(user_list) - for i, module_name in enumerate(user_list): - try: - desktop_icon = get_user_copy(module_name, user=user.name) - desktop_icon.db_set('idx', i) - except frappe.DoesNotExistError: - pass - - # set remaining icons as hidden - for module_name in list(set([m['module_name'] for m in modules_list]) - set(user_list)): - try: - desktop_icon = get_user_copy(module_name, user=user.name) - desktop_icon.db_set('hidden', 1) - except frappe.DoesNotExistError: - pass diff --git a/frappe/patches/v7_0/desktop_icons_hidden_by_admin_as_blocked.py b/frappe/patches/v7_0/desktop_icons_hidden_by_admin_as_blocked.py deleted file mode 100644 index 496af17cd2..0000000000 --- a/frappe/patches/v7_0/desktop_icons_hidden_by_admin_as_blocked.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def execute(): - # all icons hidden in standard are "blocked" - # this is for the use case where the admin wants to remove icon for everyone - - # in 7.0, icons may be hidden by default, but still can be shown to the user - # e.g. Accounts, Stock etc, so we need a new property for blocked - - if frappe.db.table_exists('Desktop Icon'): - frappe.db.sql('update `tabDesktop Icon` set blocked = 1 where standard=1 and hidden=1') \ No newline at end of file diff --git a/frappe/patches/v7_2/merge_knowledge_base.py b/frappe/patches/v7_2/merge_knowledge_base.py index 81ff98230b..301d15e1dd 100644 --- a/frappe/patches/v7_2/merge_knowledge_base.py +++ b/frappe/patches/v7_2/merge_knowledge_base.py @@ -11,12 +11,6 @@ def execute(): update_routes(['Help Category', 'Help Article']) remove_from_installed_apps('knowledge_base') - # remove desktop icon - desktop_icon_name = frappe.db.get_value('Desktop Icon', - dict(module_name='Knowledge Base', type='module')) - if desktop_icon_name: - frappe.delete_doc('Desktop Icon', desktop_icon_name) - # remove module def if frappe.db.exists('Module Def', 'Knowledge Base'): frappe.delete_doc('Module Def', 'Knowledge Base') diff --git a/frappe/patches/v8_0/fix_non_english_desktop_icons.py b/frappe/patches/v8_0/fix_non_english_desktop_icons.py deleted file mode 100644 index b4389578ab..0000000000 --- a/frappe/patches/v8_0/fix_non_english_desktop_icons.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals -import frappe -from frappe.desk.doctype.desktop_icon.desktop_icon import clear_desktop_icons_cache - -def execute(): - frappe.db.sql(""" - update `tabDesktop Icon` - set module_name=_doctype, label=_doctype - where type = 'link' and _doctype != label and link like 'List/%' - """) \ No newline at end of file diff --git a/frappe/patches/v8_0/setup_email_inbox.py b/frappe/patches/v8_0/setup_email_inbox.py index 8cd8b28116..1bfe3b0b74 100644 --- a/frappe/patches/v8_0/setup_email_inbox.py +++ b/frappe/patches/v8_0/setup_email_inbox.py @@ -3,31 +3,18 @@ import frappe, json from frappe.core.doctype.user.user import ask_pass_update, setup_user_email_inbox def execute(): - """ + """ depricate email inbox page if exists remove desktop icon for email inbox page if exists patch to remove Custom DocPerm for communication + add user inbox child table entry for existing email account in not exists """ if frappe.db.exists("Page", "email_inbox"): frappe.delete_doc("Page", "email_inbox") - desktop_icon = frappe.db.get_value("Desktop Icon", { - "module_name": "Email", - "type": "Page", - "link": "email_inbox" - }) - - if desktop_icon: - frappe.delete_doc("Desktop Icon", desktop_icon) - frappe.db.sql("""update `tabCustom DocPerm` set `write`=0, email=1 where parent='Communication'""") - setup_inbox_from_email_account() - -def setup_inbox_from_email_account(): - """ add user inbox child table entry for existing email account in not exists """ - frappe.reload_doc("core", "doctype", "user_email") frappe.reload_doc("email", "doctype", "email_account") @@ -36,4 +23,4 @@ def setup_inbox_from_email_account(): for email_account in email_accounts: setup_user_email_inbox(email_account.get("name"), email_account.get("awaiting_password"), - email_account.get("email_id"), email_account.get("enabled_outgoing")) \ No newline at end of file + email_account.get("email_id"), email_account.get("enabled_outgoing")) diff --git a/frappe/patches/v8_0/update_desktop_icons.py b/frappe/patches/v8_0/update_desktop_icons.py deleted file mode 100644 index ea8527718b..0000000000 --- a/frappe/patches/v8_0/update_desktop_icons.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe.utils import cstr - -def execute(): - """ update the desktop icons """ - - frappe.reload_doc('desk', 'doctype', 'desktop_icon') - - icons = frappe.get_all("Desktop Icon", filters={ "type": "link" }, fields=["link", "name"]) - - for icon in icons: - # check if report exists - icon_link = icon.get("link", "") or "" - parts = icon_link.split("/") - if not parts: - continue - - report_name = parts[-1] - if "report" in parts[0] and frappe.db.get_value("Report", report_name): - frappe.db.sql(""" update `tabDesktop Icon` set _report='{report_name}' - where name='{name}'""".format(report_name=report_name, name=icon.get("name"))) \ No newline at end of file diff --git a/frappe/public/build.json b/frappe/public/build.json index 6e8c8a97fc..adac42b164 100755 --- a/frappe/public/build.json +++ b/frappe/public/build.json @@ -133,6 +133,7 @@ "public/js/lib/Sortable.min.js", "public/js/lib/jquery/jquery.hotkeys.js", "public/js/lib/bootstrap.min.js", + "node_modules/vue/dist/vue.js", "node_modules/moment/min/moment-with-locales.min.js", "node_modules/moment-timezone/builds/moment-timezone-with-data.min.js", "public/js/lib/socket.io.min.js", @@ -229,7 +230,6 @@ "public/js/frappe/ui/toolbar/about.js", "public/js/frappe/ui/toolbar/navbar.html", "public/js/frappe/ui/toolbar/toolbar.js", - "public/js/frappe/ui/toolbar/modules_select.js", "public/js/frappe/ui/toolbar/notifications.js", "public/js/frappe/views/communication.js", "public/js/frappe/views/translation_manager.js", @@ -381,5 +381,8 @@ ], "js/social.min.js": [ "public/js/frappe/social/social_home.js" + ], + "js/modules.min.js": [ + "public/js/frappe/views/modules_home.js" ] } diff --git a/frappe/public/js/frappe/desk.js b/frappe/public/js/frappe/desk.js index 5313f64b41..a04e4eed4b 100644 --- a/frappe/public/js/frappe/desk.js +++ b/frappe/public/js/frappe/desk.js @@ -194,7 +194,7 @@ frappe.Application = Class.extend({ load_bootinfo: function() { if(frappe.boot) { frappe.modules = {}; - frappe.boot.desktop_icons.forEach(function(m) { + frappe.boot.allowed_modules.forEach(function(m) { frappe.modules[m.module_name]=m; }); frappe.model.sync(frappe.boot.docs); @@ -264,9 +264,6 @@ frappe.Application = Class.extend({ $.extend(frappe.boot.notification_info, r.message); $(document).trigger("notification-update"); - // update in module views - me.update_notification_count_in_modules(); - if(frappe.get_route()[0] != "messages") { if(r.message.new_messages.length) { frappe.utils.set_title_prefix("(" + r.message.new_messages.length + ")"); @@ -279,18 +276,6 @@ frappe.Application = Class.extend({ } }, - update_notification_count_in_modules: function() { - $.each(frappe.boot.notification_info.open_count_doctype, function(doctype, count) { - if(count) { - $('.open-notification.global[data-doctype="'+ doctype +'"]') - .removeClass("hide").html(count > 99 ? "99+" : count); - } else { - $('.open-notification.global[data-doctype="'+ doctype +'"]') - .addClass("hide"); - } - }); - }, - set_globals: function() { frappe.session.user = frappe.boot.user.name; frappe.session.user_email = frappe.boot.user.email; @@ -591,86 +576,3 @@ frappe.get_module = function(m, default_module) { return module; }; - -frappe.get_desktop_icons = function(show_hidden, show_global) { - // filter valid icons - - // hidden == hidden from desktop - // blocked == no view from modules either - - var out = []; - - var add_to_out = function(module) { - module = frappe.get_module(module.module_name, module); - module.app_icon = frappe.ui.app_icon.get_html(module); - out.push(module); - }; - - var show_module = function(m) { - var out = true; - if(m.type==="page") { - out = m.link in frappe.boot.page_info; - } else if(m.force_show) { - out = true; - } else if(m._report) { - out = m._report in frappe.boot.user.all_reports; - } else if(m._doctype) { - //out = frappe.model.can_read(m._doctype); - out = frappe.boot.user.can_read.includes(m._doctype); - } else { - if(['Help', 'Settings'].includes(m.module_name)) { - // no permissions necessary for learn - out = true; - } else if(m.module_name==='Setup' && frappe.user.has_role('System Manager')) { - out = true; - } else { - out = frappe.boot.user.allow_modules.indexOf(m.module_name) !== -1; - } - } - if(m.hidden && !show_hidden) { - out = false; - } - if(m.blocked && !show_global) { - out = false; - } - return out; - }; - - let m; - for (var i=0, l=frappe.boot.desktop_icons.length; i < l; i++) { - m = frappe.boot.desktop_icons[i]; - if ((['Setup', 'Core'].indexOf(m.module_name) === -1) && show_module(m)) { - add_to_out(m); - } - } - - if(frappe.user_roles.includes('System Manager')) { - m = frappe.get_module('Setup'); - if(show_module(m)) add_to_out(m); - } - - if(frappe.user_roles.includes('Administrator')) { - m = frappe.get_module('Core'); - if(show_module(m)) add_to_out(m); - } - - return out; -}; - -frappe.add_to_desktop = function(label, doctype, report) { - frappe.call({ - method: 'frappe.desk.doctype.desktop_icon.desktop_icon.add_user_icon', - args: { - 'link': frappe.get_route_str(), - 'label': label, - 'type': 'link', - '_doctype': doctype, - '_report': report - }, - callback: function(r) { - if(r.message) { - frappe.show_alert(__("Added")); - } - } - }); -}; diff --git a/frappe/public/js/frappe/form/toolbar.js b/frappe/public/js/frappe/form/toolbar.js index 99d913f1cd..44898c3b5e 100644 --- a/frappe/public/js/frappe/form/toolbar.js +++ b/frappe/public/js/frappe/form/toolbar.js @@ -153,13 +153,6 @@ frappe.ui.form.Toolbar = Class.extend({ this.page.add_menu_item(__("Reload"), function() { me.frm.reload_doc();}, true); - // add to desktop - if(me.frm.meta.issingle) { - this.page.add_menu_item(__('Add to Desktop'), function () { - frappe.add_to_desktop(me.frm.doctype, me.frm.doctype); - }, true); - } - // delete if((cint(me.frm.doc.docstatus) != 1) && !me.frm.doc.__islocal && frappe.model.can_delete(me.frm.doctype)) { diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 6052baa6c4..9d47f283c8 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -1008,13 +1008,6 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { standard: true }); - // add to desktop - items.push({ - label: __('Add to Desktop'), - action: () => frappe.add_to_desktop(doctype, doctype), - standard: true - }); - if (frappe.user.has_role('System Manager') && frappe.boot.developer_mode === 1) { // edit doctype items.push({ diff --git a/frappe/public/js/frappe/misc/user.js b/frappe/public/js/frappe/misc/user.js index 4b6b52bea9..15e91a82c5 100644 --- a/frappe/public/js/frappe/misc/user.js +++ b/frappe/public/js/frappe/misc/user.js @@ -74,7 +74,7 @@ $.extend(frappe.user, { }, get_desktop_items: function() { // hide based on permission - var modules_list = $.map(frappe.boot.desktop_icons, function(icon) { + var modules_list = $.map(frappe.boot.allowed_modules, function(icon) { var m = icon.module_name; var type = frappe.modules[m] && frappe.modules[m].type; @@ -105,14 +105,6 @@ $.extend(frappe.user, { return modules_list; }, - is_module: function(m) { - var icons = frappe.get_desktop_icons(); - for(var i=0; i' + frappe._('Usage Info') + ''); + help_links.push(''); help_links.push('
  • '); $(help_links.join("\n")).insertBefore($("#toolbar-user").find("li:first")); } diff --git a/frappe/public/js/frappe/ui/toolbar/modules_select.js b/frappe/public/js/frappe/ui/toolbar/modules_select.js deleted file mode 100644 index 1b41141c9b..0000000000 --- a/frappe/public/js/frappe/ui/toolbar/modules_select.js +++ /dev/null @@ -1,108 +0,0 @@ -frappe.provide('frappe.ui.toolbar'); - -frappe.ui.toolbar.ModulesSelect = class { - constructor() { - this.user = frappe.boot.user.name; - this.setup(); - } - - setup() { - this.dialog = new frappe.ui.Dialog({ - title: __('Set Desktop Icons'), - fields: [ - { - label: __('Setup for'), - fieldname: 'setup_for', - fieldtype: 'Select', - options: [ - {label: __('User'), value: 'user'}, - {label: __('Everyone'), value: 'everyone'} - ], - default: 'user', - onchange: () => { - let field = this.$setup_for; - if(field.get_value() === 'everyone') { - this.$user.$wrapper.hide(); - this.user = undefined; - field.set_description(__('Limit icon choices for all users.')); - } else { - this.$user.$wrapper.show(); - this.user = this.$user.get_value(); - field.set_description(''); - } - this.$icons_list.refresh(); - } - }, - { fieldtype: 'Column Break' }, - { - label: __('User'), - fieldname: 'user', - fieldtype: 'Link', - options: 'User', - default: frappe.boot.user.name, - onchange: () => { - this.user = this.get_value() || frappe.boot.user.name; - this.$icons_list.refresh(); - } - }, - { fieldtype: 'Section Break' }, - { - // label: __('Icons'), - fieldname: 'icons', - fieldtype: 'MultiCheck', - select_all: 1, - columns: 2, - get_data: () => { - return new Promise((resolve) => { - frappe.call({ - method: 'frappe.desk.doctype.desktop_icon.desktop_icon.get_module_icons', - args: {user: this.user}, - freeze: true, - callback: (r) => { - const icons = r.message.icons; - const user = r.message.user; - resolve(icons - .map(icon => { - const uncheck = user ? icon.hidden : icon.blocked; - return { label: icon.label, value: icon.module_name, checked:!uncheck }; - }).sort(function(a, b){ - if(a.label < b.label) return -1; - if(a.label > b.label) return 1; - return 0; - }) - ); - } - }); - }); - } - } - ] - }); - - this.dialog.set_primary_action(__('Save'), () => { - frappe.call({ - method: 'frappe.desk.doctype.desktop_icon.desktop_icon.update_icons', - args: { - hidden_list: this.$icons_list.get_unchecked_options(), - user: this.user - }, - freeze: true, - callback: () => { - window.location.href = ''; - } - }); - }); - - this.$icons_list = this.dialog.fields_dict.icons; - this.$setup_for = this.dialog.fields_dict.setup_for; - this.$user = this.dialog.fields_dict.user; - } - - show(user) { - if(user) { - this.user = user || frappe.boot.user.name; - this.$icons_list.refresh(); - } - this.dialog.show(); - } -}; \ No newline at end of file diff --git a/frappe/public/js/frappe/ui/toolbar/navbar.html b/frappe/public/js/frappe/ui/toolbar/navbar.html index 729365f53a..ea6691a7a3 100644 --- a/frappe/public/js/frappe/ui/toolbar/navbar.html +++ b/frappe/public/js/frappe/ui/toolbar/navbar.html @@ -24,8 +24,6 @@ {%= frappe.user.full_name() %}