diff --git a/frappe/boot.py b/frappe/boot.py
index 6763583307..90e2b9c22a 100644
--- a/frappe/boot.py
+++ b/frappe/boot.py
@@ -100,7 +100,6 @@ 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/desk/moduleview.py b/frappe/desk/moduleview.py
index 5978bc7ef0..a9a460b124 100644
--- a/frappe/desk/moduleview.py
+++ b/frappe/desk/moduleview.py
@@ -302,30 +302,30 @@ def get_links(app, module):
link_names.append(item.get("label"))
return link_names
+@frappe.whitelist()
+def hide_modules_from_desktop(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
+
+
@frappe.whitelist()
-def update_desk_section_settings(desk_section, new_settings):
+def update_links_for_module(module_name, links):
home_settings = frappe.db.get_value("User", frappe.session.user, 'home_settings')
- if home_settings:
- home_settings = json.loads(home_settings)
- else:
- return {}
+ home_settings = frappe.parse_json(home_settings or '{}')
- new_settings = json.loads(new_settings)
+ home_settings.setdefault('links', {})
+ home_settings['links'].setdefault(module_name, None)
+ home_settings['links'][module_name] = links
+ frappe.db.set_value('User', frappe.session.user, 'home_settings', json.dumps(home_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
+ return home_settings
def get_module_link_items_from_list(app, module, list_of_link_names):
diff --git a/frappe/patches.txt b/frappe/patches.txt
index 43d0699647..d3b3ca02f1 100644
--- a/frappe/patches.txt
+++ b/frappe/patches.txt
@@ -238,3 +238,4 @@ 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.replace_null_values_in_tables
+frappe.patches.v12_0.reset_home_settings
\ No newline at end of file
diff --git a/frappe/patches/v12_0/reset_home_settings.py b/frappe/patches/v12_0/reset_home_settings.py
new file mode 100644
index 0000000000..db16c31f15
--- /dev/null
+++ b/frappe/patches/v12_0/reset_home_settings.py
@@ -0,0 +1,8 @@
+import frappe
+
+def execute():
+ frappe.db.sql('''
+ UPDATE `tabUser`
+ SET `home_settings` = ''
+ WHERE `user_type` = 'System User'
+ ''')
diff --git a/frappe/public/build.json b/frappe/public/build.json
index b5a89f1a9d..76cab5a040 100755
--- a/frappe/public/build.json
+++ b/frappe/public/build.json
@@ -93,6 +93,7 @@
"public/js/frappe/form/controls/multiselect.js",
"public/js/frappe/form/controls/multicheck.js",
"public/js/frappe/form/controls/table_multiselect.js",
+ "public/js/frappe/form/controls/multiselect_pills.js",
"public/js/frappe/form/controls/rating.js"
],
"js/dialog.min.js": [
diff --git a/frappe/public/js/frappe/form/controls/multiselect_pills.js b/frappe/public/js/frappe/form/controls/multiselect_pills.js
new file mode 100644
index 0000000000..8796c95eaa
--- /dev/null
+++ b/frappe/public/js/frappe/form/controls/multiselect_pills.js
@@ -0,0 +1,150 @@
+import Awesomplete from 'awesomplete';
+
+frappe.ui.form.ControlMultiSelectPills = frappe.ui.form.ControlAutocomplete.extend({
+ make_input() {
+ this._super();
+ this.$input_area = $(this.input_area);
+ this.$multiselect_wrapper = $('
')
+ .addClass('form-control table-multiselect')
+ .appendTo(this.$input_area);
+
+ this.$input.removeClass('form-control');
+ this.$input_area.find('.awesomplete').appendTo(this.$multiselect_wrapper);
+
+ this.$input.on("awesomplete-selectcomplete", () => {
+ this.$input.val('').focus();
+ });
+
+ // used as an internal model to store values
+ this.rows = [];
+
+ this.$input_area.on('click', '.btn-remove', (e) => {
+ const $target = $(e.currentTarget);
+ const $value = $target.closest('.tb-selected-value');
+
+ const value = decodeURIComponent($value.data().value);
+ this.rows = this.rows.filter(val => val !== value);
+
+ this.parse_validate_and_set_in_model('');
+ });
+
+ this.$input.on('keydown', e => {
+ // if backspace key pressed on empty input, delete last value
+ if (e.keyCode == frappe.ui.keyCode.BACKSPACE && e.target.value === '') {
+ this.rows = this.rows.slice(0, this.rows.length - 1);
+ this.parse_validate_and_set_in_model('');
+ }
+ });
+ },
+
+ parse(value) {
+ if (value) {
+ this.rows.push(value);
+ }
+
+ return this.rows;
+ },
+
+ validate(value) {
+ const rows = (value || []).slice();
+
+ if (rows.length === 0) {
+ return rows;
+ }
+
+ const all_rows_except_last = rows.slice(0, rows.length - 1);
+ const last_value = rows[rows.length - 1];
+
+ // falsy value
+ if (!last_value) {
+ return all_rows_except_last;
+ }
+
+ // duplicate value
+ if (all_rows_except_last.includes(last_value)) {
+ return all_rows_except_last;
+ }
+
+ return rows;
+ },
+
+ set_formatted_input(value) {
+ this.rows = value || [];
+ this.set_pill_html(this.rows);
+ },
+
+ set_pill_html(values) {
+ const html = values
+ .map(value => this.get_pill_html(value))
+ .join('');
+
+ this.$multiselect_wrapper.find('.tb-selected-value').remove();
+ this.$multiselect_wrapper.prepend(html);
+ },
+
+ get_pill_html(value) {
+ const encoded_value = encodeURIComponent(value);
+ return `
+
+
+
`;
+ },
+
+ get_awesomplete_settings() {
+ const settings = this._super();
+
+ return Object.assign(settings, {
+ filter: function(text, input) {
+ let d = this.get_item(text.value);
+ if(!d) {
+ return Awesomplete.FILTER_CONTAINS(text, input.match(/[^,]*$/)[0]);
+ }
+
+ let getMatch = value => Awesomplete.FILTER_CONTAINS(value, input.match(/[^,]*$/)[0]);
+
+ // match typed input with label or value or description
+ let v = getMatch(d.label);
+ if(!v && d.value) {
+ v = getMatch(d.value);
+ }
+ if(!v && d.description) {
+ v = getMatch(d.description);
+ }
+
+ return v;
+ }
+ });
+ },
+
+ get_value() {
+ return this.rows;
+ },
+
+ get_values() {
+ return this.rows;
+ },
+
+ get_data() {
+ let data;
+ if(this.df.get_data) {
+ data = this.df.get_data();
+ if (data && data.then) {
+ data.then((r) => {
+ this.set_data(r);
+ });
+ data = this.get_value();
+ } else {
+ this.set_data(data);
+ }
+ } else {
+ data = this._super();
+ }
+ const values = this.get_values() || [];
+
+ // return values which are not already selected
+ if (data) data.filter(d => !values.includes(d));
+ return data;
+ }
+});
diff --git a/frappe/public/js/frappe/views/components/DeskModuleBox.vue b/frappe/public/js/frappe/views/components/DeskModuleBox.vue
index 245b47d147..e57b128033 100644
--- a/frappe/public/js/frappe/views/components/DeskModuleBox.vue
+++ b/frappe/public/js/frappe/views/components/DeskModuleBox.vue
@@ -3,11 +3,6 @@
v-if="!hidden"
class="border module-box"
:class="{ 'hovered-box': hovered }"
- :draggable="true"
- @dragstart="on_dragstart"
- @dragend="on_dragend"
- @dragenter="on_enter"
- @drop="on_drop"
>
@@ -20,23 +15,12 @@
-
+
-
+
-
-
@@ -50,6 +34,7 @@ export default {
"index",
"name",
"label",
+ "category",
"type",
"module_name",
"link",
@@ -75,32 +60,21 @@ export default {
} else {
return "octicon octicon-file-text";
}
- }
+ },
+ dropdown_links() {
+ return this.links.length > 0 ? this.links
+ .filter(link => !link.hidden)
+ .concat([
+ { label: __('Customize'), action: () => this.$emit('customize'), class: 'border-top' }
+ ]) : [];
+ }
},
- methods: {
- on_dragstart() {
- this.$emit("box-dragstart", this.index);
- return 0;
- },
- on_dragend() {
- this.$emit("box-dragend", this.index);
- return 0;
- },
- on_enter() {
- this.$emit("box-enter", this.index);
- // this.hovered = 1;
- },
- on_drop() {
- this.$emit("box-drop", this.index);
- },
- on_exit() {
- // this.hovered = 0;
- }
- }
};
-
diff --git a/frappe/public/js/frappe/views/components/Desktop.vue b/frappe/public/js/frappe/views/components/Desktop.vue
index 74d3cc6622..f950d04e79 100644
--- a/frappe/public/js/frappe/views/components/Desktop.vue
+++ b/frappe/public/js/frappe/views/components/Desktop.vue
@@ -1,24 +1,30 @@
-