Merge pull request #7928 from netchampfaris/feat-desktop-cards-reorder
feat: Re-arrange cards on Desktop
This commit is contained in:
commit
dff5cab5ce
6 changed files with 229 additions and 103 deletions
|
|
@ -287,44 +287,141 @@ def get_onboard_items(app, module):
|
|||
|
||||
return onboard_items or fallback_items
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_links_for_module(app, module):
|
||||
return [l.get('label') for l in get_links(app, module)]
|
||||
|
||||
def get_links(app, module):
|
||||
try:
|
||||
sections = get_config(app, frappe.scrub(module))
|
||||
except ImportError:
|
||||
return []
|
||||
|
||||
link_names = []
|
||||
|
||||
links = []
|
||||
for section in sections:
|
||||
for item in section["items"]:
|
||||
link_names.append(item.get("label"))
|
||||
return link_names
|
||||
for item in section['items']:
|
||||
links.append(item)
|
||||
return links
|
||||
|
||||
@frappe.whitelist()
|
||||
def hide_modules_from_desktop(modules):
|
||||
def get_desktop_settings():
|
||||
from frappe.config import get_modules_from_all_apps_for_user
|
||||
all_modules = get_modules_from_all_apps_for_user()
|
||||
home_settings = get_home_settings()
|
||||
|
||||
modules_by_name = {}
|
||||
for m in all_modules:
|
||||
modules_by_name[m['module_name']] = m
|
||||
|
||||
module_categories = ['Modules', 'Domains', 'Places', 'Administration']
|
||||
user_modules_by_category = {}
|
||||
|
||||
user_saved_modules_by_category = home_settings.modules_by_category or {}
|
||||
user_saved_links_by_module = home_settings.links_by_module or {}
|
||||
|
||||
def apply_user_saved_links(module):
|
||||
module = frappe._dict(module)
|
||||
all_links = get_links(module.app, module.module_name)
|
||||
module_links_by_label = {}
|
||||
for link in all_links:
|
||||
module_links_by_label[link['label']] = link
|
||||
|
||||
if module.module_name in user_saved_links_by_module:
|
||||
user_links = frappe.parse_json(user_saved_links_by_module[module.module_name])
|
||||
module.links = [module_links_by_label[l] for l in user_links if l in module_links_by_label]
|
||||
|
||||
return module
|
||||
|
||||
for category in module_categories:
|
||||
if category in user_saved_modules_by_category:
|
||||
user_modules = user_saved_modules_by_category[category]
|
||||
user_modules_by_category[category] = [apply_user_saved_links(modules_by_name[m]) \
|
||||
for m in user_modules]
|
||||
else:
|
||||
user_modules_by_category[category] = [apply_user_saved_links(m) \
|
||||
for m in all_modules if m['category'] == category]
|
||||
|
||||
# filter out hidden modules
|
||||
if home_settings.hidden_modules:
|
||||
for category in user_modules_by_category:
|
||||
hidden_modules = home_settings.hidden_modules or []
|
||||
modules = user_modules_by_category[category]
|
||||
user_modules_by_category[category] = [module for module in modules if module.module_name not in hidden_modules]
|
||||
|
||||
return user_modules_by_category
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_hidden_modules(category_map):
|
||||
category_map = frappe.parse_json(category_map)
|
||||
home_settings = get_home_settings()
|
||||
|
||||
saved_hidden_modules = home_settings.hidden_modules or []
|
||||
|
||||
for category in category_map:
|
||||
config = frappe._dict(category_map[category])
|
||||
saved_hidden_modules += config.removed or []
|
||||
saved_hidden_modules = [d for d in saved_hidden_modules if d not in (config.added or [])]
|
||||
|
||||
home_settings.hidden_modules = saved_hidden_modules
|
||||
set_home_settings(home_settings)
|
||||
|
||||
return get_desktop_settings()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_modules_order(module_category, modules):
|
||||
modules = frappe.parse_json(modules)
|
||||
home_settings = frappe.db.get_value("User", frappe.session.user, 'home_settings')
|
||||
home_settings = frappe.parse_json(home_settings or '{}')
|
||||
|
||||
home_settings['hidden_modules'] = modules
|
||||
frappe.db.set_value('User', frappe.session.user, 'home_settings', json.dumps(home_settings))
|
||||
|
||||
return home_settings
|
||||
home_settings = get_home_settings()
|
||||
|
||||
home_settings.modules_by_category = home_settings.modules_by_category or {}
|
||||
home_settings.modules_by_category[module_category] = modules
|
||||
|
||||
set_home_settings(home_settings)
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_links_for_module(module_name, links):
|
||||
home_settings = frappe.db.get_value("User", frappe.session.user, 'home_settings')
|
||||
home_settings = frappe.parse_json(home_settings or '{}')
|
||||
links = frappe.parse_json(links)
|
||||
home_settings = get_home_settings()
|
||||
|
||||
home_settings.setdefault('links', {})
|
||||
home_settings['links'].setdefault(module_name, None)
|
||||
home_settings['links'][module_name] = links
|
||||
home_settings.setdefault('links_by_module', {})
|
||||
home_settings['links_by_module'].setdefault(module_name, None)
|
||||
home_settings['links_by_module'][module_name] = links
|
||||
|
||||
set_home_settings(home_settings)
|
||||
|
||||
return get_desktop_settings()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_options_for_show_hide_cards():
|
||||
from frappe.config import get_modules_from_all_apps_for_user
|
||||
all_modules = get_modules_from_all_apps_for_user()
|
||||
home_settings = get_home_settings()
|
||||
|
||||
hidden_modules = home_settings.hidden_modules or []
|
||||
|
||||
options = []
|
||||
for module in all_modules:
|
||||
module = frappe._dict(module)
|
||||
options.append({
|
||||
'category': module.category,
|
||||
'label': module.label,
|
||||
'value': module.module_name,
|
||||
'checked': module.module_name not in hidden_modules
|
||||
})
|
||||
|
||||
return options
|
||||
|
||||
def set_home_settings(home_settings):
|
||||
frappe.cache().hset('home_settings', frappe.session.user, home_settings)
|
||||
frappe.db.set_value('User', frappe.session.user, 'home_settings', json.dumps(home_settings))
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_home_settings():
|
||||
def get_from_db():
|
||||
settings = frappe.db.get_value("User", frappe.session.user, 'home_settings')
|
||||
return frappe.parse_json(settings or '{}')
|
||||
|
||||
home_settings = frappe.cache().hget('home_settings', frappe.session.user, get_from_db)
|
||||
return home_settings
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ frappe.patches.v12_0.set_primary_key_in_series
|
|||
execute:frappe.delete_doc("Page", "modules", ignore_missing=True)
|
||||
frappe.patches.v11_0.set_default_letter_head_source
|
||||
frappe.patches.v12_0.setup_comments_from_communications
|
||||
frappe.patches.v12_0.init_desk_settings #11-03-2019
|
||||
frappe.patches.v12_0.init_desk_settings #16-05-2019
|
||||
frappe.patches.v12_0.replace_null_values_in_tables
|
||||
frappe.patches.v12_0.reset_home_settings
|
||||
frappe.patches.v12_0.update_print_format_type
|
||||
|
|
|
|||
|
|
@ -8,4 +8,4 @@ from frappe.desk.moduleview import get_onboard_items
|
|||
def execute():
|
||||
"""Reset the initial customizations for desk, with modules, indices and links."""
|
||||
frappe.reload_doc("core", "doctype", "user")
|
||||
frappe.db.sql("""update `tabUser` set home_settings = %s""", (''), debug=True)
|
||||
frappe.db.sql("""update tabUser set home_settings = ''""")
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
v-if="!hidden"
|
||||
class="border module-box"
|
||||
:class="{ 'hovered-box': hovered }"
|
||||
:data-module-name="module_name"
|
||||
>
|
||||
<div class="flush-top">
|
||||
<div class="module-box-content">
|
||||
|
|
@ -10,7 +11,7 @@
|
|||
<a class="module-box-link" :href="type === 'module' ? '#modules/' + module_name : link">
|
||||
<h4 class="h4">
|
||||
<div>
|
||||
<i :class="iconClass" style="color:#8d99a6;font-size:18px;margin-right:6px;"></i>
|
||||
<i :class="icon_class" style="color:#8d99a6;font-size:18px;margin-right:6px;"></i>
|
||||
{{ label }}
|
||||
</div>
|
||||
</h4>
|
||||
|
|
@ -54,7 +55,7 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
iconClass() {
|
||||
icon_class() {
|
||||
if (this.icon) {
|
||||
return this.icon;
|
||||
} else {
|
||||
|
|
@ -82,7 +83,12 @@ export default {
|
|||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.module-box:hover {
|
||||
.module-box.sortable-chosen {
|
||||
background-color: @disabled-background;
|
||||
border-color: @disabled-background;
|
||||
}
|
||||
|
||||
.modules-container:not(.dragging) .module-box:hover {
|
||||
border-color: @text-muted;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
<div class="module-category h6 uppercase">{{ category }}</div>
|
||||
</div>
|
||||
|
||||
<div class="modules-container">
|
||||
<div class="modules-container" :class="{'dragging': dragging}" ref="modules-container">
|
||||
<desk-module-box
|
||||
v-for="(module, index) in modules"
|
||||
:key="module.name"
|
||||
:key="module.module_name"
|
||||
:index="index"
|
||||
v-bind="module"
|
||||
@customize="show_module_card_customize_dialog(module)"
|
||||
|
|
@ -24,7 +24,32 @@ export default {
|
|||
components: {
|
||||
DeskModuleBox
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dragging: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.setup_sortable();
|
||||
},
|
||||
methods: {
|
||||
setup_sortable() {
|
||||
let modules_container =this.$refs['modules-container'];
|
||||
this.sortable = new Sortable(modules_container, {
|
||||
animation: 150,
|
||||
onStart: () => this.dragging = true,
|
||||
onEnd: () => {
|
||||
this.dragging = false;
|
||||
let modules = Array.from(modules_container.querySelectorAll('.module-box'))
|
||||
.map(node => node.dataset.moduleName);
|
||||
|
||||
this.$emit('module-order-change', {
|
||||
module_category: this.category,
|
||||
modules
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
show_module_card_customize_dialog(module) {
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __('Customize Shortcuts'),
|
||||
|
|
@ -34,7 +59,7 @@ export default {
|
|||
fieldname: 'links',
|
||||
fieldtype: 'MultiSelectPills',
|
||||
get_data() {
|
||||
return frappe.call('frappe.desk.moduleview.get_links', {
|
||||
return frappe.call('frappe.desk.moduleview.get_links_for_module', {
|
||||
app: module.app,
|
||||
module: module.module_name,
|
||||
}).then(r => r.message);
|
||||
|
|
@ -48,7 +73,7 @@ export default {
|
|||
module_name: module.module_name,
|
||||
links
|
||||
}).then(r => {
|
||||
this.$emit('update_home_settings', r.message);
|
||||
this.$emit('update-desktop-settings', r.message);
|
||||
});
|
||||
d.hide();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@
|
|||
v-if="get_modules_for_category(category).length"
|
||||
:category="category"
|
||||
:modules="get_modules_for_category(category)"
|
||||
@update_home_settings="hs => update_modules_with_home_settings(hs)"
|
||||
@update-desktop-settings="update_desktop_settings"
|
||||
@module-order-change="update_module_order"
|
||||
>
|
||||
</desk-section>
|
||||
</div>
|
||||
|
|
@ -30,99 +31,96 @@ export default {
|
|||
DeskSection
|
||||
},
|
||||
data() {
|
||||
let modules_list = frappe.boot.allowed_modules
|
||||
.filter(d => (d.type==='module' || d.category==='Places') && !d.blocked)
|
||||
.map(d => {
|
||||
d.links = (d.links || []).map(link => {
|
||||
link.route = generate_route(link);
|
||||
return link;
|
||||
});
|
||||
return d;
|
||||
});
|
||||
|
||||
return {
|
||||
module_categories: ['Modules', 'Domains', 'Places', 'Administration'],
|
||||
modules: modules_list,
|
||||
modules: [],
|
||||
home_settings_fetched: false
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.fetch_home_settings();
|
||||
this.fetch_desktop_settings();
|
||||
},
|
||||
methods: {
|
||||
fetch_home_settings() {
|
||||
return frappe.db.get_value('User', user, 'home_settings')
|
||||
fetch_desktop_settings() {
|
||||
frappe.call('frappe.desk.moduleview.get_desktop_settings')
|
||||
.then(r => {
|
||||
let home_settings = JSON.parse(r.message.home_settings || '{}');
|
||||
this.update_modules_with_home_settings(home_settings);
|
||||
this.home_settings_fetched = true;
|
||||
if (r.message) {
|
||||
this.update_desktop_settings(r.message);
|
||||
this.home_settings_fetched = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
update_modules_with_home_settings(home_settings) {
|
||||
this.modules = this.modules.map(m => {
|
||||
let hidden_modules = home_settings.hidden_modules || [];
|
||||
m.hidden = hidden_modules.includes(m.module_name);
|
||||
|
||||
let links = home_settings.links && home_settings.links[m.module_name];
|
||||
|
||||
if (links) {
|
||||
links = JSON.parse(links);
|
||||
|
||||
let default_links = m.links.map(link => link.name);
|
||||
m.links = m.links.map(link => {
|
||||
link.hidden = !links.includes(link.name);
|
||||
update_desktop_settings(desktop_settings) {
|
||||
this.modules = this.add_routes_for_module_links(desktop_settings);
|
||||
},
|
||||
add_routes_for_module_links(user_settings) {
|
||||
for (let category in user_settings) {
|
||||
user_settings[category] = user_settings[category].map(m => {
|
||||
m.links = (m.links || []).map(link => {
|
||||
link.route = generate_route(link);
|
||||
return link;
|
||||
});
|
||||
let new_links = links
|
||||
.filter(link => !default_links.includes(link))
|
||||
.filter(Boolean)
|
||||
.map(link => {
|
||||
let new_link = { name: link, label: link, type: 'doctype' };
|
||||
new_link.route = generate_route(new_link);
|
||||
return new_link;
|
||||
});
|
||||
m.links = m.links.concat(new_links);
|
||||
}
|
||||
|
||||
return m;
|
||||
});
|
||||
return m;
|
||||
});
|
||||
}
|
||||
return user_settings;
|
||||
},
|
||||
update_module_order({ module_category, modules }) {
|
||||
frappe.call('frappe.desk.moduleview.update_modules_order', { module_category, modules });
|
||||
},
|
||||
get_modules_for_category(category) {
|
||||
return this.modules.filter(m => m.category === category && !m.hidden);
|
||||
return this.modules[category] || [];
|
||||
},
|
||||
show_hide_cards_dialog() {
|
||||
let fields = this.module_categories.map(category => {
|
||||
let modules = this.modules.filter(m => m.category === category);
|
||||
let options = modules.map(
|
||||
m => ({ label: m.label, value: m.module_name, checked: !m.hidden })
|
||||
);
|
||||
return {
|
||||
label: category,
|
||||
fieldname: category,
|
||||
fieldtype: 'MultiCheck',
|
||||
options,
|
||||
columns: 2
|
||||
}
|
||||
});
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __('Show / Hide Cards'),
|
||||
fields: fields.filter(f => f.options.length > 0),
|
||||
primary_action_label: __('Save'),
|
||||
primary_action: (values) => {
|
||||
let all_modules = this.modules.map(m => m.module_name);
|
||||
let modules_to_show = Object.keys(values).map(k => values[k]).flatMap(m => m);
|
||||
let modules_to_hide = all_modules.filter(m => !modules_to_show.includes(m));
|
||||
d.hide();
|
||||
frappe.call('frappe.desk.moduleview.get_options_for_show_hide_cards')
|
||||
.then(r => {
|
||||
let module_options = r.message;
|
||||
let fields = this.module_categories.map(category => {
|
||||
let options = module_options.filter(m => m.category === category);
|
||||
return {
|
||||
label: category,
|
||||
fieldname: category,
|
||||
fieldtype: 'MultiCheck',
|
||||
options,
|
||||
columns: 2
|
||||
}
|
||||
}).filter(f => f.options.length > 0);
|
||||
|
||||
frappe.call('frappe.desk.moduleview.hide_modules_from_desktop', {
|
||||
modules: modules_to_hide
|
||||
})
|
||||
.then(r => r.message)
|
||||
.then(hs => this.update_modules_with_home_settings(hs));
|
||||
}
|
||||
});
|
||||
let old_values = null;
|
||||
|
||||
d.show();
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __('Show / Hide Cards'),
|
||||
fields: fields,
|
||||
primary_action_label: __('Save'),
|
||||
primary_action: (values) => {
|
||||
|
||||
let category_map = {};
|
||||
for (let category of this.module_categories) {
|
||||
let old_modules = old_values[category] || [];
|
||||
let new_modules = values[category] || [];
|
||||
|
||||
let removed = old_modules.filter(module => !new_modules.includes(module));
|
||||
let added = new_modules.filter(module => !old_modules.includes(module));
|
||||
|
||||
category_map[category] = { added, removed };
|
||||
}
|
||||
|
||||
frappe.call({
|
||||
method: 'frappe.desk.moduleview.update_hidden_modules',
|
||||
args: { category_map },
|
||||
btn: d.get_primary_btn()
|
||||
}).then(r => {
|
||||
this.update_desktop_settings(r.message)
|
||||
d.hide();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
d.show();
|
||||
|
||||
// deepcopy
|
||||
old_values = JSON.parse(JSON.stringify(d.get_values()));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue