diff --git a/frappe/desk/doctype/tag/tag.json b/frappe/desk/doctype/tag/tag.json
index 7522d9471a..895516594e 100644
--- a/frappe/desk/doctype/tag/tag.json
+++ b/frappe/desk/doctype/tag/tag.json
@@ -4,8 +4,7 @@
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
- "description",
- "count"
+ "description"
],
"fields": [
{
@@ -13,15 +12,9 @@
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Description"
- },
- {
- "fieldname": "count",
- "fieldtype": "Int",
- "label": "Count",
- "read_only": 1
}
],
- "modified": "2019-09-24 00:53:13.488147",
+ "modified": "2019-09-25 17:47:41.712237",
"modified_by": "Administrator",
"module": "Desk",
"name": "Tag",
diff --git a/frappe/public/js/frappe/ui/toolbar/global_tags.js b/frappe/public/js/frappe/ui/toolbar/global_tags.js
index bf4cb2293b..f8fbb39c8b 100644
--- a/frappe/public/js/frappe/ui/toolbar/global_tags.js
+++ b/frappe/public/js/frappe/ui/toolbar/global_tags.js
@@ -2,109 +2,14 @@
// MIT License. See license.txt
frappe.provide("frappe.global_tags");
-frappe.provide("locals.global_tags");
-
-frappe.global_tags.GlobalTagsDialog = class GlobalTags {
- constructor(opts) {
- $.extend(this, opts);
- this.show();
- }
-
- show() {
- if (!this.dialog) {
- this.make_dialog();
- }
-
- $(this.dialog.body).html(
- `
- ${__("Loading")}...
-
`);
-
- this.dialog.show();
- }
-
- make_dialog() {
- let title = __("Tag {0}", ["#".concat(this.tag)]);
-
- this.dialog = new frappe.ui.Dialog({
- hide_on_page_refresh: true,
- minimizable: true,
- title: title
- });
-
- this.dialog.on_page_show = () => {
- this.get_documents_for_tag()
- .then(() => this.make_html());
- };
- }
-
- make_html() {
- const results = this.results;
- let html = '';
-
- const linked_doctypes = Object.keys(results);
-
- if (linked_doctypes.length === 0) {
- html = __("Not Linked to any record");
- } else {
- html = linked_doctypes.map(doctype => {
- const docs = results[doctype];
- return `
-
- ${this.make_doc_head(doctype)}
- ${docs.map(doc => this.make_doc_row(doc.dn, doctype, doc.title)).join('')}
-
- `;
- }).join('');
- }
-
- $(this.dialog.body).html(html);
- }
-
- get_documents_for_tag() {
- return new Promise((resolve) => {
- frappe.call({
- method: "frappe.utils.global_tags.get_documents_for_tag",
- args: {
- tag: this.tag
- },
- callback: (r) => {
- this.results = r.message;
- resolve();
- }
- });
- });
- }
-
- make_doc_head(heading) {
- return `
-
- `;
- }
-
- make_doc_row(docname, doctype, title) {
- return ``;
- }
-};
frappe.global_tags.utils = {
get_tags: function(txt) {
txt = txt.slice(1);
let out = [];
- for (let i in locals.global_tags) {
- let tag = locals.global_tags[i];
+ for (let i in frappe.global_tags.tags) {
+ let tag = frappe.global_tags.tags[i];
let level = frappe.search.utils.fuzzy_search(txt, tag);
if (level) {
out.push({
@@ -113,8 +18,9 @@ frappe.global_tags.utils = {
value: __("#{0}", [__(tag)]),
index: 1 + level,
match: tag,
- onclick: function() {
- new frappe.global_tags.GlobalTagsDialog({"tag": tag});
+ onclick() {
+ // Use Global Search Dialog for tag search too.
+ frappe.searchdialog.search.init_search("#".concat(tag), "global_tag")
}
});
}
@@ -123,14 +29,130 @@ frappe.global_tags.utils = {
return out;
},
- set_tags: function() {
+ set_tags() {
frappe.call({
method: "frappe.utils.global_tags.get_tags_list_for_awesomebar",
callback: function(r) {
if (r && r.message) {
- locals.global_tags = $.extend([], r.message);
+ frappe.global_tags.tags = $.extend([], r.message);
}
}
});
- }
-}
\ No newline at end of file
+ },
+
+ get_tag_results: function(tag) {
+ var me = this;
+ function get_results_sets(data) {
+ var results_sets = [], result, set;
+ function get_existing_set(doctype) {
+ return results_sets.find(function(set) {
+ return set.title === doctype;
+ });
+ }
+
+ function make_description(content, doc_name) {
+ var parts = content.split(" ||| ");
+ var result_max_length = 300;
+ var field_length = 120;
+ var fields = [];
+ var result_current_length = 0;
+ var field_text = "";
+ for(var i = 0; i < parts.length; i++) {
+ var part = parts[i];
+ if(part.toLowerCase().indexOf(tag) !== -1) {
+ // If the field contains the keyword
+ if(part.indexOf(' &&& ') !== -1) {
+ var colon_index = part.indexOf(' &&& ');
+ var field_value = part.slice(colon_index + 5);
+ } else {
+ var colon_index = part.indexOf(' : ');
+ var field_value = part.slice(colon_index + 3);
+ }
+ if(field_value.length > field_length) {
+ // If field value exceeds field_length, find the keyword in it
+ // and trim field value by half the field_length at both sides
+ // ellipsify if necessary
+ var field_data = "";
+ var index = field_value.indexOf(tag);
+ field_data += index < field_length/2 ? field_value.slice(0, index)
+ : '...' + field_value.slice(index - field_length/2, index);
+ field_data += field_value.slice(index, index + field_length/2);
+ field_data += index + field_length/2 < field_value.length ? "..." : "";
+ field_value = field_data;
+ }
+ var field_name = part.slice(0, colon_index);
+
+ // Find remaining result_length and add field length to result_current_length
+ var remaining_length = result_max_length - result_current_length;
+ result_current_length += field_name.length + field_value.length + 2;
+ if(result_current_length < result_max_length) {
+ // We have room, push the entire field
+ field_text = '' +
+ me.bolden_match_part(field_name, tag) + ': ' +
+ me.bolden_match_part(field_value, tag);
+ if(fields.indexOf(field_text) === -1 && doc_name !== field_value) {
+ fields.push(field_text);
+ }
+ } else {
+ // Not enough room
+ if(field_name.length < remaining_length){
+ // Ellipsify (trim at word end) and push
+ remaining_length -= field_name.length;
+ field_text = '' +
+ me.bolden_match_part(field_name, tag) + ': ';
+ field_value = field_value.slice(0, remaining_length);
+ field_value = field_value.slice(0, field_value.lastIndexOf(' ')) + ' ...';
+ field_text += me.bolden_match_part(field_value, tag);
+ fields.push(field_text);
+ } else {
+ // No room for even the field name, skip
+ fields.push('...');
+ }
+ break;
+ }
+ }
+ }
+ return fields.join(', ');
+ }
+
+ data.forEach(function(d) {
+ // more properties
+ result = {
+ label: d.name,
+ value: d.name,
+ description: make_description(d.content, d.name),
+ route: ['Form', d.doctype, d.name],
+
+ };
+ set = get_existing_set(d.doctype);
+ if(set) {
+ set.results.push(result);
+ } else {
+ set = {
+ title: d.doctype,
+ results: [result],
+ fetch_type: "Global"
+ };
+ results_sets.push(set);
+ }
+
+ });
+ return results_sets;
+ }
+ return new Promise(function(resolve, reject) {
+ frappe.call({
+ method: "frappe.utils.global_tags.get_documents_for_tag",
+ args: {
+ tag: tag
+ },
+ callback: function(r) {
+ if(r.message) {
+ resolve(get_results_sets(r.message));
+ } else {
+ resolve([]);
+ }
+ }
+ });
+ });
+ },
+}
diff --git a/frappe/public/js/frappe/ui/toolbar/search.js b/frappe/public/js/frappe/ui/toolbar/search.js
index e27c383ec4..ac50a35a60 100644
--- a/frappe/public/js/frappe/ui/toolbar/search.js
+++ b/frappe/public/js/frappe/ui/toolbar/search.js
@@ -124,6 +124,10 @@ frappe.search.SearchDialog = Class.extend({
// Help results
// this.$modal_body.on('click', 'a[data-path]', frappe.help.show_results);
this.bind_keyboard_events();
+
+ // Setup Minimizable functionality
+ this.search_dialog.minimizable = true;
+ this.search_dialog.$wrapper.find('.btn-modal-minimize').click(() => this.toggle_minimize());
},
bind_keyboard_events: function() {
@@ -308,7 +312,7 @@ frappe.search.SearchDialog = Class.extend({
frappe.route_options = result.route_options;
}
$result.on('click', (e) => {
- this.search_dialog.hide();
+ this.toggle_minimize();
if(result.onclick) {
result.onclick(result.match);
} else {
@@ -353,6 +357,19 @@ frappe.search.SearchDialog = Class.extend({
this.$modal_body.find('.more-results.last').slideDown(200, function() {});
},
+ get_minimize_btn: function() {
+ return this.search_dialog.$wrapper.find(".modal-header .btn-modal-minimize");
+ },
+
+ toggle_minimize: function() {
+ let modal = this.search_dialog.$wrapper.closest('.modal').toggleClass('modal-minimize');
+ modal.attr('tabindex') ? modal.removeAttr('tabindex') : modal.attr('tabindex', -1);
+ this.get_minimize_btn().find('i').toggleClass('octicon-chevron-down').toggleClass('octicon-chevron-up');
+ this.search_dialog.is_minimized = !this.search_dialog.is_minimized;
+ this.on_minimize_toggle && this.on_minimize_toggle(this.search_dialog.is_minimized);
+ this.search_dialog.header.find('.modal-title').toggleClass('cursor-pointer');
+ },
+
// Search objects
searches: {
global_search: {
@@ -372,6 +389,22 @@ frappe.search.SearchDialog = Class.extend({
});
}
},
+ global_tag: {
+ input_placeholder: __("Global Tags"),
+ empty_state_text: __("Search for Tags"),
+ no_results_status: (keyword) => __("No results found for '" + keyword + "' in Global Tags
"),
+
+ get_results: function(keywords, callback) {
+ var results = frappe.search.utils.get_nav_results(keywords);
+ frappe.global_tags.utils.get_tag_results(keywords)
+ .then(function(global_results) {
+ results = results.concat(global_results);
+ callback(results, keywords);
+ }, function (err) {
+ console.error(err);
+ });
+ }
+ },
},
});
\ No newline at end of file
diff --git a/frappe/public/js/frappe/ui/toolbar/search_header.html b/frappe/public/js/frappe/ui/toolbar/search_header.html
index f36e87c7ea..4b8b70ad97 100644
--- a/frappe/public/js/frappe/ui/toolbar/search_header.html
+++ b/frappe/public/js/frappe/ui/toolbar/search_header.html
@@ -1,6 +1,13 @@
\ No newline at end of file
diff --git a/frappe/utils/global_tags.py b/frappe/utils/global_tags.py
index d13e4e2cc3..3c061d057a 100644
--- a/frappe/utils/global_tags.py
+++ b/frappe/utils/global_tags.py
@@ -48,7 +48,10 @@ def get_documents_for_tag(tag):
:param tag: tag to be searched
"""
# remove hastag `#` from tag
- results = {}
+ tag = tag[1:]
+
+ results = []
+
tag = frappe.db.escape('%{0}%'.format(tag.lower()), False)
result = frappe.db.sql('''
@@ -58,10 +61,11 @@ def get_documents_for_tag(tag):
'''.format(tag), as_dict=True)
for res in result:
- if res.dt in results.keys():
- results[res.dt].append(res)
- else:
- results[res.dt] = [res]
+ results.append({
+ "doctype": res.dt,
+ "name": res.dn,
+ "content": res.title
+ })
return results