mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 00:42:41 +01:00
Share more code between tokenizers and global typeahead
Summary: Ref T4420. Fixes T5306. Currently, the main menubar search has a lot of redundant/unshared code. Move some common functions into `JX.Prefab.whatever()` and call them from the main search. The major change here is that we apply the same "only show closed/disabled/archived objects if there are no matching open objects" logic, fixing T5306. Test Plan: - Used normal typeaheads. - Used global search. - Searched for a prefix shared by open and archived projects, didn't see the archived ones until the open ones were exhausted. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5306, T4420 Differential Revision: https://secure.phabricator.com/D9899
This commit is contained in:
parent
c52b3c28e1
commit
a592b32ca4
3 changed files with 127 additions and 117 deletions
|
@ -8,7 +8,7 @@
|
|||
return array(
|
||||
'names' => array(
|
||||
'core.pkg.css' => 'c2c68e64',
|
||||
'core.pkg.js' => '80884e9b',
|
||||
'core.pkg.js' => '0095fb2c',
|
||||
'darkconsole.pkg.js' => 'df001cab',
|
||||
'differential.pkg.css' => '4a93db37',
|
||||
'differential.pkg.js' => '7528cfc9',
|
||||
|
@ -450,7 +450,7 @@ return array(
|
|||
'rsrc/js/core/KeyboardShortcutManager.js' => 'ad7a69ca',
|
||||
'rsrc/js/core/MultirowRowManager.js' => '41e47dea',
|
||||
'rsrc/js/core/Notification.js' => '0c6946e7',
|
||||
'rsrc/js/core/Prefab.js' => '41ed7994',
|
||||
'rsrc/js/core/Prefab.js' => 'c11bac49',
|
||||
'rsrc/js/core/ShapedRequest.js' => '7cbe244b',
|
||||
'rsrc/js/core/TextAreaUtils.js' => 'b3ec3cfc',
|
||||
'rsrc/js/core/ToolTip.js' => '3915d490',
|
||||
|
@ -485,7 +485,7 @@ return array(
|
|||
'rsrc/js/core/behavior-remarkup-preview.js' => 'f7379f45',
|
||||
'rsrc/js/core/behavior-reorder-applications.js' => '76b9fc3e',
|
||||
'rsrc/js/core/behavior-reveal-content.js' => '60821bc7',
|
||||
'rsrc/js/core/behavior-search-typeahead.js' => '5a376f34',
|
||||
'rsrc/js/core/behavior-search-typeahead.js' => 'd712ac5f',
|
||||
'rsrc/js/core/behavior-select-on-click.js' => '4e3e79a6',
|
||||
'rsrc/js/core/behavior-toggle-class.js' => 'e566f52c',
|
||||
'rsrc/js/core/behavior-tokenizer.js' => 'b3a4b884',
|
||||
|
@ -629,7 +629,7 @@ return array(
|
|||
'javelin-behavior-phabricator-oncopy' => '2926fff2',
|
||||
'javelin-behavior-phabricator-remarkup-assist' => 'e32d14ab',
|
||||
'javelin-behavior-phabricator-reveal-content' => '60821bc7',
|
||||
'javelin-behavior-phabricator-search-typeahead' => '5a376f34',
|
||||
'javelin-behavior-phabricator-search-typeahead' => 'd712ac5f',
|
||||
'javelin-behavior-phabricator-show-all-transactions' => '7c273581',
|
||||
'javelin-behavior-phabricator-tooltips' => '3ee3408b',
|
||||
'javelin-behavior-phabricator-transaction-comment-form' => '9f7309fb',
|
||||
|
@ -737,7 +737,7 @@ return array(
|
|||
'phabricator-notification-menu-css' => '8ae4a008',
|
||||
'phabricator-object-selector-css' => '029a133d',
|
||||
'phabricator-phtize' => 'd254d646',
|
||||
'phabricator-prefab' => '41ed7994',
|
||||
'phabricator-prefab' => 'c11bac49',
|
||||
'phabricator-profile-css' => 'b459416e',
|
||||
'phabricator-remarkup-css' => 'ad4c0676',
|
||||
'phabricator-search-results-css' => 'f240504c',
|
||||
|
@ -1126,18 +1126,6 @@ return array(
|
|||
2 => 'javelin-dom',
|
||||
3 => 'javelin-util',
|
||||
),
|
||||
'41ed7994' => array(
|
||||
0 => 'javelin-install',
|
||||
1 => 'javelin-util',
|
||||
2 => 'javelin-dom',
|
||||
3 => 'javelin-typeahead',
|
||||
4 => 'javelin-tokenizer',
|
||||
5 => 'javelin-typeahead-preloaded-source',
|
||||
6 => 'javelin-typeahead-ondemand-source',
|
||||
7 => 'javelin-dom',
|
||||
8 => 'javelin-stratcom',
|
||||
9 => 'javelin-util',
|
||||
),
|
||||
'44168bad' => array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-dom',
|
||||
|
@ -1232,15 +1220,6 @@ return array(
|
|||
2 => 'javelin-vector',
|
||||
3 => 'javelin-dom',
|
||||
),
|
||||
'5a376f34' => array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-typeahead-ondemand-source',
|
||||
2 => 'javelin-typeahead',
|
||||
3 => 'javelin-dom',
|
||||
4 => 'javelin-uri',
|
||||
5 => 'javelin-util',
|
||||
6 => 'javelin-stratcom',
|
||||
),
|
||||
'5bc2cb21' => array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-stratcom',
|
||||
|
@ -1690,6 +1669,18 @@ return array(
|
|||
2 => 'javelin-util',
|
||||
3 => 'phabricator-shaped-request',
|
||||
),
|
||||
'c11bac49' => array(
|
||||
0 => 'javelin-install',
|
||||
1 => 'javelin-util',
|
||||
2 => 'javelin-dom',
|
||||
3 => 'javelin-typeahead',
|
||||
4 => 'javelin-tokenizer',
|
||||
5 => 'javelin-typeahead-preloaded-source',
|
||||
6 => 'javelin-typeahead-ondemand-source',
|
||||
7 => 'javelin-dom',
|
||||
8 => 'javelin-stratcom',
|
||||
9 => 'javelin-util',
|
||||
),
|
||||
'c4569c05' => array(
|
||||
0 => 'javelin-magical-init',
|
||||
1 => 'javelin-install',
|
||||
|
@ -1764,6 +1755,16 @@ return array(
|
|||
2 => 'javelin-stratcom',
|
||||
3 => 'javelin-dom',
|
||||
),
|
||||
'd712ac5f' => array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-typeahead-ondemand-source',
|
||||
2 => 'javelin-typeahead',
|
||||
3 => 'javelin-dom',
|
||||
4 => 'javelin-uri',
|
||||
5 => 'javelin-util',
|
||||
6 => 'javelin-stratcom',
|
||||
7 => 'phabricator-prefab',
|
||||
),
|
||||
'd75709e6' => array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-workflow',
|
||||
|
|
|
@ -31,6 +31,7 @@ JX.install('Prefab', {
|
|||
return select;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Build a Phabricator tokenizer out of a configuration with application
|
||||
* sorting, datasource and placeholder rules.
|
||||
|
@ -142,82 +143,9 @@ JX.install('Prefab', {
|
|||
});
|
||||
};
|
||||
|
||||
var render_icon = function(icon) {
|
||||
return JX.$N(
|
||||
'span',
|
||||
{className: 'phui-icon-view phui-font-fa ' + icon});
|
||||
};
|
||||
|
||||
datasource.setSortHandler(JX.bind(datasource, sort_handler));
|
||||
|
||||
// Don't show any closed objects until the query is specific enough that
|
||||
// it only selects closed objects. Specifically, if the result list had
|
||||
// any open objects, remove all the closed objects from the list.
|
||||
var filter_handler = function(value, list) {
|
||||
// Look for any open result.
|
||||
var has_open = false;
|
||||
var ii;
|
||||
for (ii = 0; ii < list.length; ii++) {
|
||||
if (!list[ii].closed) {
|
||||
has_open = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_open) {
|
||||
// Everything is closed, so just use it as-is.
|
||||
return list;
|
||||
}
|
||||
|
||||
// Otherwise, only display the open results.
|
||||
var results = [];
|
||||
for (ii = 0; ii < list.length; ii++) {
|
||||
if (!list[ii].closed) {
|
||||
results.push(list[ii]);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
datasource.setFilterHandler(filter_handler);
|
||||
|
||||
datasource.setTransformer(
|
||||
function(object) {
|
||||
var closed = object[9];
|
||||
var closed_ui;
|
||||
if (closed) {
|
||||
closed_ui = JX.$N(
|
||||
'div',
|
||||
{className: 'tokenizer-closed'},
|
||||
closed);
|
||||
}
|
||||
|
||||
var icon = object[8];
|
||||
var icon_ui;
|
||||
if (icon) {
|
||||
icon_ui = render_icon(icon);
|
||||
}
|
||||
|
||||
var display = JX.$N(
|
||||
'div',
|
||||
{className: 'tokenizer-result'},
|
||||
[icon_ui, object[0], closed_ui]);
|
||||
if (closed) {
|
||||
JX.DOM.alterClass(display, 'tokenizer-result-closed', true);
|
||||
}
|
||||
|
||||
return {
|
||||
name: object[0],
|
||||
display: display,
|
||||
uri: object[1],
|
||||
id: object[2],
|
||||
priority: object[3],
|
||||
priorityType: object[7],
|
||||
icon: icon,
|
||||
closed: closed
|
||||
};
|
||||
});
|
||||
datasource.setFilterHandler(JX.Prefab.filterClosedResults);
|
||||
datasource.setTransformer(JX.Prefab.transformDatasourceResults);
|
||||
|
||||
var typeahead = new JX.Typeahead(
|
||||
root,
|
||||
|
@ -238,7 +166,7 @@ JX.install('Prefab', {
|
|||
return value;
|
||||
}
|
||||
|
||||
icon = render_icon(icon);
|
||||
icon = JX.Prefab._renderIcon(icon);
|
||||
|
||||
// TODO: Maybe we should render these closed tags in grey? Figure out
|
||||
// how we're going to use color.
|
||||
|
@ -263,7 +191,89 @@ JX.install('Prefab', {
|
|||
return {
|
||||
tokenizer: tokenizer
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Filter callback for tokenizers and typeaheads which filters out closed
|
||||
* or disabled objects unless they are the only options.
|
||||
*/
|
||||
filterClosedResults: function(value, list) {
|
||||
// Look for any open result.
|
||||
var has_open = false;
|
||||
var ii;
|
||||
for (ii = 0; ii < list.length; ii++) {
|
||||
if (!list[ii].closed) {
|
||||
has_open = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_open) {
|
||||
// Everything is closed, so just use it as-is.
|
||||
return list;
|
||||
}
|
||||
|
||||
// Otherwise, only display the open results.
|
||||
var results = [];
|
||||
for (ii = 0; ii < list.length; ii++) {
|
||||
if (!list[ii].closed) {
|
||||
results.push(list[ii]);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
/**
|
||||
* Transform results from a wire format into a usable format in a standard
|
||||
* way.
|
||||
*/
|
||||
transformDatasourceResults: function(fields) {
|
||||
var closed = fields[9];
|
||||
var closed_ui;
|
||||
if (closed) {
|
||||
closed_ui = JX.$N(
|
||||
'div',
|
||||
{className: 'tokenizer-closed'},
|
||||
closed);
|
||||
}
|
||||
|
||||
var icon = fields[8];
|
||||
var icon_ui;
|
||||
if (icon) {
|
||||
icon_ui = JX.Prefab._renderIcon(icon);
|
||||
}
|
||||
|
||||
var display = JX.$N(
|
||||
'div',
|
||||
{className: 'tokenizer-result'},
|
||||
[icon_ui, fields[4] || fields[0], closed_ui]);
|
||||
if (closed) {
|
||||
JX.DOM.alterClass(display, 'tokenizer-result-closed', true);
|
||||
}
|
||||
|
||||
return {
|
||||
name: fields[0],
|
||||
displayName: fields[4] || fields[0],
|
||||
display: display,
|
||||
uri: fields[1],
|
||||
id: fields[2],
|
||||
priority: fields[3],
|
||||
priorityType: fields[7],
|
||||
imageURI: fields[6],
|
||||
icon: icon,
|
||||
closed: closed,
|
||||
type: fields[5],
|
||||
sprite: fields[10]
|
||||
};
|
||||
},
|
||||
|
||||
_renderIcon: function(icon) {
|
||||
return JX.$N(
|
||||
'span',
|
||||
{className: 'phui-icon-view phui-font-fa ' + icon});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* javelin-uri
|
||||
* javelin-util
|
||||
* javelin-stratcom
|
||||
* phabricator-prefab
|
||||
*/
|
||||
|
||||
JX.behavior('phabricator-search-typeahead', function(config) {
|
||||
|
@ -14,31 +15,28 @@ JX.behavior('phabricator-search-typeahead', function(config) {
|
|||
var datasource = new JX.TypeaheadOnDemandSource(config.src);
|
||||
|
||||
function transform(object) {
|
||||
object = JX.Prefab.transformDatasourceResults(object);
|
||||
|
||||
var attr = {
|
||||
className: 'phabricator-main-search-typeahead-result'
|
||||
};
|
||||
|
||||
if (object[6]) {
|
||||
attr.style = {backgroundImage: 'url('+object[6]+')'};
|
||||
if (object.imageURI) {
|
||||
attr.style = {backgroundImage: 'url('+object.imageURI+')'};
|
||||
}
|
||||
|
||||
var render = JX.$N(
|
||||
'span',
|
||||
attr,
|
||||
[
|
||||
JX.$N('span', {className: object[10]}),
|
||||
JX.$N('span', {className: 'result-name'}, object[4] || object[0]),
|
||||
JX.$N('span', {className: 'result-type'}, object[5])
|
||||
JX.$N('span', {className: object.sprite}),
|
||||
JX.$N('span', {className: 'result-name'}, object.displayName),
|
||||
JX.$N('span', {className: 'result-type'}, object.type)
|
||||
]);
|
||||
|
||||
return {
|
||||
name: object[0],
|
||||
display: render,
|
||||
uri: object[1],
|
||||
id: object[2],
|
||||
priority: object[3],
|
||||
type: object[7]
|
||||
};
|
||||
object.display = render;
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
datasource.setTransformer(transform);
|
||||
|
@ -76,8 +74,8 @@ JX.behavior('phabricator-search-typeahead', function(config) {
|
|||
}
|
||||
|
||||
list.sort(function(u, v) {
|
||||
var u_type = type_priority[u.type] || 999;
|
||||
var v_type = type_priority[v.type] || 999;
|
||||
var u_type = type_priority[u.priorityType] || 999;
|
||||
var v_type = type_priority[v.priorityType] || 999;
|
||||
|
||||
if (u_type != v_type) {
|
||||
return u_type - v_type;
|
||||
|
@ -120,6 +118,7 @@ JX.behavior('phabricator-search-typeahead', function(config) {
|
|||
};
|
||||
|
||||
datasource.setSortHandler(JX.bind(datasource, sort_handler));
|
||||
datasource.setFilterHandler(JX.Prefab.filterClosedResults);
|
||||
datasource.setMaximumResultCount(config.limit);
|
||||
|
||||
var typeahead = new JX.Typeahead(JX.$(config.id), JX.$(config.input));
|
||||
|
|
Loading…
Reference in a new issue