Merge pull request #6821 from pratu16x7/explore-2.0
feat(explore_page): Modules and Module Detail views
This commit is contained in:
commit
056daa8a73
60 changed files with 854 additions and 1256 deletions
|
|
@ -120,6 +120,7 @@
|
|||
"md5": true,
|
||||
"$": true,
|
||||
"jQuery": true,
|
||||
"Vue": true,
|
||||
"moment": true,
|
||||
"hljs": true,
|
||||
"Awesomplete": true,
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}]
|
||||
|
|
@ -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,
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
First screen after login. Array of module icons based on permission.
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<div><input class="form-control desktop-app-search" type="text" placeholder="{%= __("Search Application") %}">
|
||||
</div>
|
||||
{% if (frappe.user.has_role("System Manager")) { %}
|
||||
<p class="text-right"><a href="#applications" class="btn btn-sm btn-default">Install new applications</a>
|
||||
</p>
|
||||
{% } %}
|
||||
<hr>
|
||||
<p class="text-muted small">{%= __("Checked items will be shown on desktop") %}</p>
|
||||
<div class="list-group all-applications-list">
|
||||
{% 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; }
|
||||
%}
|
||||
<div class="list-group-item" data-label="{%= module.label %}" data-name="{%= module.name %}">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" {% if (user_desktop_items.indexOf(module.name)!==-1) { %} checked {% } %}
|
||||
data-name="{%= module.name %}"
|
||||
{{ module.force_show ? "disabled" : ""}}> {%= __(module.label) %}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{% } %}
|
||||
</div>
|
||||
|
|
@ -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 = $('<div class="help-message-item hidden"></div>')
|
||||
.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 =
|
||||
`
|
||||
<div class="circle module-remove" style="background-color:#E0E0E0; color:#212121">
|
||||
<div class="circle-text">
|
||||
<b>
|
||||
×
|
||||
</b>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
$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() {};
|
||||
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -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'))))
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
<div><span class="indicator blue">{{ title }}</span></div>
|
||||
<p>{{ description }}</p>
|
||||
<div>
|
||||
<a class="btn btn-sm btn-default" href="#{{ route }}">{{ action }}</a>
|
||||
<span class="help-progress" title="{{ __("You have made {0} of {1}", [count, target]) }}">
|
||||
<span class="help-progress-bar" style="width: {{ Math.floor(count/target*100) }}%"></span>
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
<div style="text-align: center; padding-top: calc(40px + 3%)">
|
||||
<div id="icon-grid">
|
||||
{% for (var i=0, l=desktop_items.length; i < l; i++) { %}
|
||||
{{ frappe.render_template("desktop_module_icon", desktop_items[i]) }}
|
||||
{% } %}
|
||||
</div>
|
||||
<div class="help-message-wrapper hidden">
|
||||
<div class="help-message-container">
|
||||
<a class="close pull-right" style="margin-right: -7px;">
|
||||
<i class="octicon octicon-x"></i></a>
|
||||
<div class="help-messages">
|
||||
|
||||
</div>
|
||||
<a class="left-arrow octicon octicon-chevron-left">
|
||||
</a>
|
||||
<a class="right-arrow octicon octicon-chevron-right">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
<div class="container page-body">
|
||||
<div class="row">
|
||||
<div class="layout-main-section">
|
||||
<div class="page-content desktop-list" style="margin-top: 40px;">
|
||||
{% for (var i=0, l=desktop_items.length; i < l; i++) {
|
||||
var module = desktop_items[i];
|
||||
%}
|
||||
<div class="desktop-list-item" id="module-icon-{%= module._id %}"
|
||||
data-name="{%= module.name %}" data-link="{%= module.link %}"
|
||||
title="{%= module._label %}">
|
||||
<h4>
|
||||
<i class="{{ module.icon }} text-muted"
|
||||
style="font-size: 20px; margin-right: 15px;"></i>
|
||||
{{ module._label }}
|
||||
</h4>
|
||||
<span class="open-notification global module-count-{{ module._id }}"
|
||||
style="display: none;"></span>
|
||||
</div>
|
||||
{% } %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
<div class="case-wrapper"
|
||||
data-name="{{ module_name }}" data-link="{{ link }}" title="{{ _label }}">
|
||||
{{ app_icon }}
|
||||
<div class="case-label ellipsis">
|
||||
<div class="circle module-count-{{ frappe.scrub(_id) }}" data-doctype="{{ _doctype }}" style="display: none;">
|
||||
<span class="circle-text"></span>
|
||||
</div>
|
||||
<!-- <span id="module-count-{{ _id }}" class="octicon octicon-primitive-dot circle" style="display: None"></span> -->
|
||||
<span class="case-label-text">{{ _label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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) => `<li class="strong module-sidebar-item">
|
||||
<a class="module-link" data-name="${item.module_name}" href="#${item.link}">
|
||||
<i class="fa fa-chevron-right pull-right" style="display: none;"></i>
|
||||
<span>${item._label}</span>
|
||||
</a>
|
||||
</li>`;
|
||||
|
||||
let get_sidebar_html = () => {
|
||||
let sidebar_items_html = page.get_page_modules()
|
||||
.map(get_module_sidebar_item.bind(this)).join("");
|
||||
|
||||
return `<ul class="module-sidebar-nav overlay-sidebar nav nav-pills nav-stacked">
|
||||
${sidebar_items_html}
|
||||
<li class="divider"></li>
|
||||
</ul>`;
|
||||
};
|
||||
|
||||
// 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'));
|
||||
}
|
||||
};
|
||||
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
<div class="module-body">
|
||||
{% for (var i=0; i < data.length; i++) { var section = data[i]; %}
|
||||
{% if ((i % 2)===0) { %}<div class="row module-section">{% } %}
|
||||
<div class="col-sm-6 module-section-column">
|
||||
<div class="h4 section-head">
|
||||
{{ section.label }}
|
||||
</div>
|
||||
<div class="section-body">
|
||||
{% for (var j=0; j < section.items.length; j++) {
|
||||
var item = section.items[j];
|
||||
if(item.shown) { %}
|
||||
<div style="min-height: 22px; margin-top: 8px;">
|
||||
<a class="module-section-link small" data-type="{{ item.type }}"
|
||||
{% if(item.type==="help") { %}
|
||||
data-youtube-id="{{ item.youtube_id }}"{% } %}
|
||||
href="#{{ item.route }}" style="{{ item.style }}">
|
||||
{{ item.label || __(item.name) }}
|
||||
</a>
|
||||
{% if(item.type==="doctype") { %}
|
||||
<span class="open-notification global hide"
|
||||
data-doctype="{{ item.doctype || item.name }}"></span>
|
||||
{% } %}
|
||||
</div>
|
||||
{% } %}
|
||||
{% } %}
|
||||
</div>
|
||||
</div>
|
||||
{% if ((i % 2)===1 || i===data.length-1) { %}</div>{% } %}
|
||||
{% } %}
|
||||
</div>
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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')
|
||||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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/%'
|
||||
""")
|
||||
|
|
@ -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"))
|
||||
email_account.get("email_id"), email_account.get("enabled_outgoing"))
|
||||
|
|
|
|||
|
|
@ -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")))
|
||||
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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<icons.length; i++) {
|
||||
if(m===icons[i].module_name) return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
is_report_manager: function() {
|
||||
return frappe.user.has_role(['Administrator', 'System Manager', 'Report Manager']);
|
||||
},
|
||||
|
|
@ -147,9 +139,9 @@ $.extend(frappe.user, {
|
|||
/* Normally frappe.user is an object
|
||||
* having properties and methods.
|
||||
* But in the following case
|
||||
*
|
||||
*
|
||||
* if (frappe.user === 'Administrator')
|
||||
*
|
||||
*
|
||||
* frappe.user will cast to a string
|
||||
* returning frappe.user.name
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ $(document).on("toolbar_setup", function() {
|
|||
|
||||
if(limits.space || limits.users || limits.expiry || limits.emails) {
|
||||
help_links = [];
|
||||
help_links.push('<li><a href="#usage-info">' + frappe._('Usage Info') + '</a></li>');
|
||||
help_links.push('<li class="usage-info-link"><a href="#usage-info">' + frappe._('Usage Info') + '</a></li>');
|
||||
help_links.push('<li class="divider"></li>');
|
||||
$(help_links.join("\n")).insertBefore($("#toolbar-user").find("li:first"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
|
@ -24,8 +24,6 @@
|
|||
{%= frappe.user.full_name() %}</span>
|
||||
<b class="caret hidden-xs hidden-sm"></b></a>
|
||||
<ul class="dropdown-menu" id="toolbar-user" role="menu">
|
||||
<li class="navbar-set-desktop-icons"><a>
|
||||
{%= __("Set Desktop Icons") %}</a></li>
|
||||
<li><a href="#Form/User/{%= encodeURIComponent(frappe.session.user) %}">
|
||||
{%= __("My Settings") %}</a></li>
|
||||
<li class="navbar-reload">
|
||||
|
|
|
|||
|
|
@ -21,21 +21,12 @@ frappe.ui.toolbar.Toolbar = Class.extend({
|
|||
make: function() {
|
||||
this.setup_sidebar();
|
||||
this.setup_help();
|
||||
this.setup_modules_dialog();
|
||||
|
||||
this.bind_events();
|
||||
|
||||
$(document).trigger('toolbar_setup');
|
||||
},
|
||||
|
||||
|
||||
setup_modules_dialog() {
|
||||
this.modules_select = new frappe.ui.toolbar.ModulesSelect();
|
||||
$('.navbar-set-desktop-icons').on('click', () => {
|
||||
this.modules_select.show();
|
||||
});
|
||||
},
|
||||
|
||||
bind_events: function() {
|
||||
$(document).on("notification-update", function() {
|
||||
frappe.ui.notifications.update_notifications();
|
||||
|
|
|
|||
|
|
@ -40,7 +40,9 @@ frappe.breadcrumbs = {
|
|||
var breadcrumbs = frappe.breadcrumbs.all[frappe.breadcrumbs.current_page()];
|
||||
|
||||
if(!frappe.visible_modules) {
|
||||
frappe.visible_modules = $.map(frappe.get_desktop_icons(true), (m) => { return m.module_name; });
|
||||
frappe.visible_modules = $.map(frappe.boot.allowed_modules, (m) => {
|
||||
return m.module_name;
|
||||
});
|
||||
}
|
||||
|
||||
var $breadcrumbs = $("#navbar-breadcrumbs").empty();
|
||||
|
|
@ -88,7 +90,6 @@ frappe.breadcrumbs = {
|
|||
}
|
||||
if(breadcrumbs.doctype && frappe.get_route()[0]==="Form") {
|
||||
if(breadcrumbs.doctype==="User"
|
||||
&& frappe.user.is_module("Setup")===-1
|
||||
|| frappe.get_doc('DocType', breadcrumbs.doctype).issingle) {
|
||||
// no user listview for non-system managers and single doctypes
|
||||
} else {
|
||||
|
|
|
|||
151
frappe/public/js/frappe/views/components/Desktop.vue
Normal file
151
frappe/public/js/frappe/views/components/Desktop.vue
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
<template>
|
||||
<div class="modules-page-container">
|
||||
<div v-for="category in module_categories"
|
||||
:key="category">
|
||||
|
||||
<div v-if="modules.filter(m => m.category === category).length" class="module-category h6 uppercase">
|
||||
{{ category }}
|
||||
</div>
|
||||
|
||||
<div class="modules-container">
|
||||
<a v-for="module in modules.filter(m => m.category === category )"
|
||||
:key="module.name"
|
||||
:href="module.type === 'module' ? '#modules/' + module.module_name : module.link"
|
||||
class="border module-box"
|
||||
>
|
||||
<div class="flush-top">
|
||||
<div class="module-box-content">
|
||||
<h4 class="h4">
|
||||
<span class="indicator" :class="module.count ? 'red' : (module.onboard_present ? 'orange' : 'grey')"></span>
|
||||
{{ module.label }}
|
||||
</h4>
|
||||
<p class="small text-muted"> {{ module.description }} </p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
let modules_list = frappe.boot.allowed_modules
|
||||
.filter(d => (d.type==='module' || d.category==='Places') && !d.blocked);
|
||||
|
||||
modules_list.forEach(module => {
|
||||
module.count = this.get_module_count(module.module_name);
|
||||
});
|
||||
|
||||
return {
|
||||
route_str: frappe.get_route()[1],
|
||||
module_label: '',
|
||||
module_categories: ["Modules", "Domains", "Places", "Administration"],
|
||||
modules: modules_list
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
get_module_count(module_name) {
|
||||
var module_doctypes = frappe.boot.notification_info.module_doctypes[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_name]!=null) {
|
||||
// notification count explicitly for doctype
|
||||
let count = frappe.boot.notification_info.open_count_doctype[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_name]!=null) {
|
||||
// notification count explicitly for module
|
||||
let count = frappe.boot.notification_info.open_count_module[module_name] || 0;
|
||||
count = typeof count == "string" ? parseInt(count) : count;
|
||||
sum += count;
|
||||
}
|
||||
|
||||
sum = sum > 99 ? "99+" : sum;
|
||||
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.modules-page-container {
|
||||
margin: 70px 0px;
|
||||
}
|
||||
|
||||
.module-category {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 15px;
|
||||
border-bottom: 1px solid #d0d8dd;
|
||||
}
|
||||
|
||||
.modules-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
|
||||
column-gap: 15px;
|
||||
row-gap: 15px;
|
||||
}
|
||||
|
||||
.module-box {
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
padding: 5px 15px;
|
||||
padding-top: 3px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.module-box:hover {
|
||||
background-color: #fafbfc;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.module-box-content {
|
||||
padding-right: 15px;
|
||||
flex: 1;
|
||||
|
||||
h4 {
|
||||
margin-bottom: 5px
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 5px;
|
||||
font-size: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-box {
|
||||
padding: 15px;
|
||||
width: 54px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.open-notification {
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
58
frappe/public/js/frappe/views/components/ModuleDetail.vue
Normal file
58
frappe/public/js/frappe/views/components/ModuleDetail.vue
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-if="sections.length" class="sections-container">
|
||||
<div v-for="section in sections"
|
||||
:key="section.label"
|
||||
class="border section-box"
|
||||
>
|
||||
<h4 class="h4"> {{ section.label }} </h4>
|
||||
<module-link-item v-for="item in section.items"
|
||||
:key="section.label + item.label"
|
||||
:data-youtube-id="item.type==='help' ? item.youtube_id : false"
|
||||
v-bind="item"
|
||||
:open_count="item.type==='doctype' ? frappe.boot.notification_info.open_count_doctype[item.doctype] : false"
|
||||
>
|
||||
</module-link-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="sections-container">
|
||||
<div v-for="n in 3" :key="n" class="skeleton-section-box"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ModuleLinkItem from "./ModuleLinkItem.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ModuleLinkItem
|
||||
},
|
||||
props: ['module_name', 'sections'],
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.sections-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
|
||||
column-gap: 15px;
|
||||
row-gap: 15px;
|
||||
}
|
||||
|
||||
.section-box {
|
||||
padding: 5px 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.skeleton-section-box {
|
||||
background-color: #f5f7fa;
|
||||
height: 250px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.h4 {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
</style>
|
||||
106
frappe/public/js/frappe/views/components/ModuleLinkItem.vue
Normal file
106
frappe/public/js/frappe/views/components/ModuleLinkItem.vue
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
<template>
|
||||
<div class="link-item flush-top small"
|
||||
:class="{'onboard-spotlight': onboard, 'disabled-link': disabled_dependent}"
|
||||
@mouseover="mouseover" @mouseleave="mouseleave"
|
||||
>
|
||||
<span :class="['indicator', indicator_color]"></span>
|
||||
|
||||
<span v-if="disabled_dependent" class="link-content text-muted">{{ label || __(name) }}</span>
|
||||
<a v-else class="link-content" :href="route">{{ label || __(name) }}</a>
|
||||
|
||||
<div v-if="disabled_dependent" v-show="popover_active"
|
||||
@mouseover="popover_hover = true" @mouseleave="popover_hover = false"
|
||||
class="module-link-popover popover fade top in" role="tooltip"
|
||||
>
|
||||
<div class="arrow"></div>
|
||||
<h3 class="popover-title" style="display: none;"></h3>
|
||||
<div class="popover-content">
|
||||
<div class="small text-muted">{{ __("You need to create these first: ") }}</div>
|
||||
<div class="small">{{ __(incomplete_dependencies.join(", ")) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['label', 'name', 'dependencies', 'incomplete_dependencies', 'onboard', 'count', 'route', 'doctype', 'open_count'],
|
||||
data() {
|
||||
return {
|
||||
hover: false,
|
||||
popover_hover: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
disabled_dependent() {
|
||||
return this.dependencies && this.incomplete_dependencies;
|
||||
},
|
||||
|
||||
indicator_color() {
|
||||
if(this.open_count) {
|
||||
return 'red';
|
||||
}
|
||||
if(this.onboard) {
|
||||
return this.count ? 'blue' : 'orange';
|
||||
};
|
||||
return 'grey';
|
||||
},
|
||||
|
||||
popover_active() {
|
||||
return this.popover_hover || this.hover;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
mouseover() {
|
||||
$('.module-link-popover').hide();
|
||||
this.hover = true;
|
||||
},
|
||||
|
||||
mouseleave() {
|
||||
setTimeout(() => {
|
||||
this.hover = false;
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="less" scoped>
|
||||
.link-item {
|
||||
position: relative;
|
||||
margin: 10px 0px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.onboard-spotlight {
|
||||
.link-content {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
a:hover, a:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
// Overriding indicator styles
|
||||
.indicator {
|
||||
margin-right: 5px;
|
||||
color: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
.link-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.popover {
|
||||
display: block;
|
||||
top: -60px;
|
||||
max-width: 220px;
|
||||
}
|
||||
|
||||
.popover.top > .arrow {
|
||||
left: 20%;
|
||||
}
|
||||
</style>
|
||||
138
frappe/public/js/frappe/views/components/Modules.vue
Normal file
138
frappe/public/js/frappe/views/components/Modules.vue
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
<template>
|
||||
<div class="modules-page-container">
|
||||
<module-detail v-if="this.route && modules_list.map(m => m.module_name).includes(route[1])" :module_name="route[1]" :sections="current_module_sections"></module-detail>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ModuleDetail from './ModuleDetail.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ModuleDetail
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
route: frappe.get_route(),
|
||||
current_module_label: '',
|
||||
current_module_sections: [],
|
||||
modules_data_cache: {},
|
||||
modules_list: frappe.boot.allowed_modules
|
||||
.filter(d => (d.type==='module' || d.category==='Places') && !d.blocked),
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.update_current_module();
|
||||
},
|
||||
mounted() {
|
||||
frappe.module_links = {};
|
||||
frappe.route.on('change', () => {
|
||||
this.update_current_module();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
update_current_module() {
|
||||
let route = frappe.get_route();
|
||||
if(route[0] === 'modules' || !route[0]) {
|
||||
this.route = route;
|
||||
let module = this.modules_list.filter(m => m.module_name == route[1])[0];
|
||||
let module_name = module && (module.label || module.module_name);
|
||||
let title = this.current_module_label ? this.current_module_label : module_name;
|
||||
|
||||
frappe.modules.home && frappe.modules.home.page.set_title(title);
|
||||
|
||||
if(!frappe.modules.home) {
|
||||
setTimeout(() => {
|
||||
frappe.modules.home.page.set_title(title);
|
||||
}, 200);
|
||||
}
|
||||
|
||||
if(module_name) {
|
||||
this.get_module_sections(module.module_name);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get_module_sections(module_name) {
|
||||
let cache = this.modules_data_cache[module_name];
|
||||
if(cache) {
|
||||
this.current_module_sections = cache;
|
||||
} else {
|
||||
this.current_module_sections = [];
|
||||
return frappe.call({
|
||||
method: "frappe.desk.moduleview.get",
|
||||
args: {
|
||||
module: module_name,
|
||||
},
|
||||
callback: (r) => {
|
||||
var m = frappe.get_module(module_name);
|
||||
this.current_module_sections = r.message.data;
|
||||
this.process_data(module_name, this.current_module_sections);
|
||||
this.modules_data_cache[module_name] = this.current_module_sections;
|
||||
},
|
||||
freeze: true,
|
||||
});
|
||||
}
|
||||
},
|
||||
process_data(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;
|
||||
}
|
||||
|
||||
item.route = '#' + item.route;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.modules-page-container {
|
||||
margin: 15px 0px;
|
||||
}
|
||||
|
||||
</style>
|
||||
24
frappe/public/js/frappe/views/modules_home.js
Normal file
24
frappe/public/js/frappe/views/modules_home.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import Modules from './components/Modules.vue';
|
||||
|
||||
frappe.provide('frappe.modules');
|
||||
|
||||
frappe.modules.Home = class {
|
||||
constructor({ parent }) {
|
||||
this.$parent = $(parent);
|
||||
this.page = parent.page;
|
||||
this.setup_header();
|
||||
this.make_body();
|
||||
}
|
||||
make_body() {
|
||||
this.$modules_container = this.$parent.find('.layout-main');
|
||||
Vue.prototype.__ = window.__;
|
||||
Vue.prototype.frappe = window.frappe;
|
||||
new Vue({
|
||||
el: this.$modules_container[0],
|
||||
render: h => h(Modules)
|
||||
});
|
||||
}
|
||||
setup_header() {
|
||||
// subtitle
|
||||
}
|
||||
};
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// MIT License. See license.txt
|
||||
|
||||
import Desktop from './components/Desktop.vue';
|
||||
|
||||
frappe.provide('frappe.views.pageview');
|
||||
frappe.provide("frappe.standard_pages");
|
||||
|
||||
|
|
@ -39,6 +41,22 @@ frappe.views.pageview = {
|
|||
show: function(name) {
|
||||
if(!name) {
|
||||
name = (frappe.boot ? frappe.boot.home_page : window.page_name);
|
||||
|
||||
if(name === "desktop") {
|
||||
let page = frappe.container.add_page('desktop');
|
||||
frappe.container.change_to('desktop');
|
||||
|
||||
let container = $('<div class="container"></div>').appendTo(page);
|
||||
container = $('<div></div>').appendTo(container);
|
||||
|
||||
Vue.prototype.__ = window.__;
|
||||
Vue.prototype.frappe = window.frappe;
|
||||
new Vue({
|
||||
el: container[0],
|
||||
render: h => h(Desktop)
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
frappe.model.with_doctype("Page", function() {
|
||||
frappe.views.pageview.with_page(name, function(r) {
|
||||
|
|
@ -82,7 +100,6 @@ frappe.views.Page = Class.extend({
|
|||
}
|
||||
|
||||
this.trigger_page_event('on_page_load');
|
||||
|
||||
// set events
|
||||
$(this.wrapper).on('show', function() {
|
||||
window.cur_frm = null;
|
||||
|
|
@ -144,3 +161,27 @@ frappe.show_message_page = function(opts) {
|
|||
|
||||
frappe.container.change_to(opts.page_name);
|
||||
};
|
||||
|
||||
frappe.views.ModulesFactory = class ModulesFactory extends frappe.views.Factory {
|
||||
show() {
|
||||
if (frappe.pages.modules) {
|
||||
frappe.container.change_to('modules');
|
||||
} else {
|
||||
this.make('modules');
|
||||
}
|
||||
}
|
||||
|
||||
make(page_name) {
|
||||
const assets = [
|
||||
'/assets/js/modules.min.js'
|
||||
];
|
||||
|
||||
frappe.require(assets, () => {
|
||||
frappe.modules.home = new frappe.modules.Home({
|
||||
parent: this.make_page(true, page_name)
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -961,12 +961,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
|
|||
}),
|
||||
condition: () => frappe.model.can_set_user_permissions('Report'),
|
||||
standard: true
|
||||
},
|
||||
{
|
||||
label: __('Add to Desktop'),
|
||||
action: () => frappe.add_to_desktop(this.report_name, null, this.report_name),
|
||||
standard: true
|
||||
},
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1188,17 +1188,6 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
});
|
||||
}
|
||||
|
||||
// add to desktop
|
||||
items.push({
|
||||
label: __('Add to Desktop'),
|
||||
action: () => {
|
||||
frappe.add_to_desktop(
|
||||
this.report_name || __('{0} Report', [this.doctype]),
|
||||
this.doctype, this.report_name
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return items.map(i => Object.assign(i, { standard: true }));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,11 +107,6 @@ frappe.views.ReportView = frappe.ui.BaseList.extend({
|
|||
this.set_tag_and_status_filter();
|
||||
this.setup_listview_settings();
|
||||
|
||||
// add to desktop
|
||||
this.page.add_menu_item(__("Add to Desktop"), function() {
|
||||
frappe.add_to_desktop(me.docname || __('{0} Report', [me.doctype]), me.doctype, me.docname);
|
||||
}, true);
|
||||
|
||||
},
|
||||
|
||||
make_new_and_refresh: function() {
|
||||
|
|
|
|||
|
|
@ -373,14 +373,6 @@ frappe.views.TreeView = Class.extend({
|
|||
me.page.add_menu_item(menu_item["label"], menu_item["action"]);
|
||||
}
|
||||
});
|
||||
|
||||
// last menu item
|
||||
me.page.add_menu_item(__('Add to Desktop'), () => {
|
||||
const label = me.doctype === 'Account' ?
|
||||
__('Chart of Accounts') :
|
||||
__(me.doctype);
|
||||
frappe.add_to_desktop(label, me.doctype);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,6 @@
|
|||
@icon-color: @light-bg;
|
||||
@icon-hover: #fff;
|
||||
|
||||
body[data-route=""] .navbar-default, body[data-route="desktop"] .navbar-default {
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
border-color: rgba(54, 65, 76, 0.1);
|
||||
}
|
||||
|
||||
#page-desktop {
|
||||
min-width: 100%;
|
||||
margin-top: 0px;
|
||||
|
|
|
|||
|
|
@ -116,8 +116,6 @@ def get_dict(fortype, name=None):
|
|||
messages += frappe.db.sql("select 'DocType:', name from tabDocType")
|
||||
messages += frappe.db.sql("select 'Role:', name from tabRole")
|
||||
messages += frappe.db.sql("select 'Module:', name from `tabModule Def`")
|
||||
messages += frappe.db.sql("select 'Module:', label from `tabDesktop Icon` where standard=1 or owner=%s",
|
||||
frappe.session.user)
|
||||
|
||||
message_dict = make_dict_from_messages(messages)
|
||||
message_dict.update(get_dict_from_hooks(fortype, name))
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ function watch_assets() {
|
|||
|
||||
case 'BUNDLE_START': {
|
||||
const output = event.output[0];
|
||||
if (output.endsWith('.js')) {
|
||||
if (output.endsWith('.js', '.vue')) {
|
||||
log('Rebuilding', path.basename(event.output[0]));
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue