diff --git a/frappe/boot.py b/frappe/boot.py index 043c1b0361..05117acb7a 100644 --- a/frappe/boot.py +++ b/frappe/boot.py @@ -98,6 +98,7 @@ def load_conf_settings(bootinfo): def load_desktop_icons(bootinfo): from frappe.config import get_modules_from_all_apps_for_user bootinfo.allowed_modules = get_modules_from_all_apps_for_user() + bootinfo.home_settings = frappe.db.get_value("User", frappe.session.user, 'home_settings','') def get_allowed_pages(): return get_user_pages_or_reports('Page') diff --git a/frappe/config/__init__.py b/frappe/config/__init__.py index a5bdaa0a6a..0170424645 100644 --- a/frappe/config/__init__.py +++ b/frappe/config/__init__.py @@ -15,55 +15,18 @@ def get_modules_from_all_apps_for_user(user=None): empty_tables_by_module = get_all_empty_tables_by_module() - home_settings = frappe.db.get_value("User", frappe.session.user, 'home_settings') - if home_settings: - home_settings = json.loads(home_settings) - for module in allowed_modules_list: module_name = module.get("module_name") - category = module.get("category") # Apply onboarding status if module_name in empty_tables_by_module: module["onboard_present"] = 1 - # Apply customizations. Format of user settings: - # home_settings = { # <--- Settings - # "Domains": { # <--- Category (Desk Section) - # "Manufacturing": { # <--- Module - # "index": 3, - # "links": [], - # "hidden": 1, - # }, - # - # }, - # } - if home_settings: - category_settings = home_settings.get(category, '') - if category_settings: - module_settings = category_settings.get(module_name) - if module_settings: - # Set links - custom_links = module_settings.get("links") - if custom_links: - module["links"] = get_module_link_items_from_list(module["app"], module_name, custom_links.split(",")) - - # Set hidden - module["hidden"] = module_settings.get("hidden", 0) - - # Set index, (drap and drop customizations) - index = module_settings.get("index") - if not index: - index = 0 - - module["index"] = index - - # Set defaults if no customizations were set - if not module.get("links"): - module["links"] = get_onboard_items(module["app"], frappe.scrub(module_name))[:5] + # Set defaults links + module["links"] = get_onboard_items(module["app"], frappe.scrub(module_name))[:5] return allowed_modules_list diff --git a/frappe/desk/moduleview.py b/frappe/desk/moduleview.py index 3997c51c16..2c576393ca 100644 --- a/frappe/desk/moduleview.py +++ b/frappe/desk/moduleview.py @@ -304,12 +304,28 @@ def get_links(app, module): @frappe.whitelist() -def get_module_link_items_from_dict(module_link_list_map): - module_link_list_map = json.loads(module_link_list_map) - module_links = {} - for module, data in module_link_list_map.items(): - module_links[module] = get_module_link_items_from_list(data["app"], module, data["links"]) - return module_links +def update_desk_section_settings(desk_section, new_settings): + home_settings = frappe.db.get_value("User", frappe.session.user, 'home_settings') + if home_settings: + home_settings = json.loads(home_settings) + else: + return + + new_settings = json.loads(new_settings) + + for module, data in new_settings.items(): + if data.get("links"): + data["links"] = get_module_link_items_from_list(data["app"], module, data.get("links")) + data.pop("app", None) + + home_settings[desk_section] = new_settings + settings_json_str = json.dumps(home_settings) + # # This didn't work + # frappe.db.set_value("User", frappe.session.user, 'home_settings', json.dumps(home_settings)) + frappe.db.sql("""update tabUser set home_settings = %s""", (settings_json_str), debug=True) + frappe.db.commit() + + return new_settings def get_module_link_items_from_list(app, module, list_of_link_names): diff --git a/frappe/public/js/frappe/views/components/DeskSection.vue b/frappe/public/js/frappe/views/components/DeskSection.vue index 0aab01366b..342b6d3a03 100644 --- a/frappe/public/js/frappe/views/components/DeskSection.vue +++ b/frappe/public/js/frappe/views/components/DeskSection.vue @@ -32,25 +32,18 @@ import DeskModuleBox from "./DeskModuleBox.vue"; import { generate_route } from './utils.js'; export default { - props: ['category', 'all_modules'], + props: ['category', 'all_modules', 'customization_settings'], components: { DeskModuleBox }, data() { - let template_modules = this.all_modules; - template_modules.forEach(module => { - if(module.links) { - module.links.forEach(link => { - link.route = generate_route(link); - }); - } - }); + let default_modules = this.all_modules; + let modules = this.get_customized_modules(default_modules, this.customization_settings); return { - template_modules: template_modules, - modules: template_modules.slice(), - settings: {}, - all_settings: {}, + default_modules: default_modules, + modules: modules, + new_settings: {}, dragged_index: -1, hovered_index: -1, } @@ -66,17 +59,13 @@ export default { }, make_fields() { let fields = []; - let template_modules = this.template_modules; - // let selected_modules = Object.keys(this.settings); - - template_modules.forEach(module => { + this.modules.forEach(module => { fields.push(this.get_module_select_field(module)); if(module.links) { fields.push(this.get_links_multiselect_field(module)); } }); - return fields; }, make_and_show_dialog(fields) { @@ -85,31 +74,7 @@ export default { fields: fields, primary_action_label: __("Update"), primary_action: (values) => { - // Figure out the diff from the default settings known from modules - - let module_link_list_map = {}; - - Object.keys(values).forEach(module_name => { - if(!module_name.includes('links') && values[module_name]) { - const links_str = values[module_name + '_links'] || ''; - this.settings[module_name]["links"] = links_str; - if(values[module_name]) { - module_link_list_map[module_name] = { - links: links_str.split(","), - app: this.template_modules.filter(m => m.module_name === module_name)[0].app - }; - } - } - }); - - frappe.db.set_value('User', user, 'home_settings', this.all_settings) - .then((resp) => { - this.update_modules(module_link_list_map); - this.dialog.hide(); - }) - .fail((err) => { - frappe.msgprint(err); - }); + this.update_settings(values); } }); @@ -119,31 +84,92 @@ export default { this.dialog.show(); }, - update_modules(module_link_list_map) { - frappe.call({ - type: "GET", - method:'frappe.desk.moduleview.get_module_link_items_from_dict', - freeze: true, - args: { - module_link_list_map: module_link_list_map - }, - callback: (r) => { - const module_links_dict = r.message; - this.template_modules.map((m, i) => { - let raw_links = module_links_dict[m.module_name]; - raw_links.forEach(link => { - link.route = generate_route(link); - }); - if(Object.keys(module_link_list_map).includes(m.module_name)) { - m.hidden = 0; - m.links = raw_links; - } else { - m.hidden = 1; - } - }); + update_settings(values) { + // Figure out the diff from the default settings known from modules + let new_settings = {}; + const checkbox_fields = Object.keys(values).filter(f => !f.includes('links')); - this.modules = this.template_modules.filter(m => !m.hidden); + checkbox_fields.forEach(module_name => { + const default_module = this.default_modules.filter(f => f.module_name === module_name)[0]; + + // Check if hidden changed + const default_hidden = default_module.hidden ? 1 : 0; + const new_hidden = !values[module_name] ? 1 : 0; + const hidden_changed = new_hidden != default_hidden; + + // Check if links changed + let links_changed = 0; + let new_links = []; + + if(!new_hidden) { + const default_links = default_module.links.map(l => (l.name || l.label)); + const new_links_str = values[module_name + '_links'] || ''; + new_links = new_links_str ? new_links_str.split(",") : []; + links_changed = !this.are_arrays_equal(new_links, default_links); } + + // Make new settings + let new_module_settings; + + if(hidden_changed || links_changed) { + new_module_settings = {}; + if(hidden_changed) { + new_module_settings.hidden = new_hidden; + } + if(links_changed) { + new_module_settings.links = new_links; + } + } + + if(new_module_settings) { + new_module_settings.app = this.default_modules.filter(m => m.module_name === module_name)[0].app; + new_settings[module_name] = new_module_settings; + } + }); + + if(Object.keys(new_settings)) { + frappe.call({ + type: "GET", + method:'frappe.desk.moduleview.update_desk_section_settings', + freeze: true, + args: { + desk_section: this.category, + new_settings: new_settings + }, + callback: (r) => { + let new_settings_with_link_objects = r.message; + let home_settings = JSON.parse(frappe.boot.home_settings); + home_settings[this.category] = new_settings_with_link_objects; + frappe.boot.home_settings = JSON.stringify(home_settings); + + this.modules = this.get_customized_modules(this.default_modules, new_settings_with_link_objects); + this.dialog.hide(); + } + }); + } else { + this.dialog.hide(); + }; + }, + + get_customized_modules(default_modules, customization_settings) { + return default_modules.map(module => { + let customized_module = JSON.parse(JSON.stringify(module)); + + const module_settings = customization_settings[module.module_name]; + if(module_settings) { + if(module_settings.links) { + customized_module.links = module_settings.links; + } + customized_module.hidden = module_settings ? module_settings.hidden : 0; + } + + if(customized_module.links) { + customized_module.links.forEach(link => { + link.route = generate_route(link); + }); + } + + return customized_module; }); }, @@ -184,6 +210,15 @@ export default { }; }, + are_arrays_equal(arr1, arr2) { + if(arr1.length !== arr2.length) return false; + let areEqual = true; + arr1.map((d, i) => { + if(arr2[i] !== d) areEqual = false; + }); + return areEqual; + }, + box_dragstart(index) { this.dragged_index = index; }, diff --git a/frappe/public/js/frappe/views/components/Desktop.vue b/frappe/public/js/frappe/views/components/Desktop.vue index 125f59d803..76753aade5 100644 --- a/frappe/public/js/frappe/views/components/Desktop.vue +++ b/frappe/public/js/frappe/views/components/Desktop.vue @@ -8,6 +8,7 @@ v-if="modules.filter(m => m.category === category).length" :category="category" :all_modules="modules.filter(m => m.category === category)" + :customization_settings="home_settings[category] || {}" > @@ -35,10 +36,32 @@ export default { route_str: frappe.get_route()[1], module_label: '', module_categories: ["Modules", "Domains", "Places", "Administration"], - modules: modules_list + modules: modules_list, + + // // Desk customizations. Format of user settings: + + // home_settings = { // <--- Settings + // "Domains": { // <--- Category (Desk Section) + // "Manufacturing": { // <--- Module + // "index": 3, + // "links": [], + // "hidden": 1, + // }, + + // }, + // } + + home_settings: JSON.parse(frappe.boot.home_settings) }; }, methods: { + get_settings() { + return frappe.db.get_value('User', user, 'home_settings') + .then(resp => { + this.all_settings = JSON.parse(resp.message['home_settings']); + this.settings = this.all_settings[this.category]; + }); + }, get_module_count(module_name) { var module_doctypes = frappe.boot.notification_info.module_doctypes[module_name]; var sum = 0;