1
0
Fork 0
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:
epriestley 2014-07-17 15:52:58 -07:00
parent c52b3c28e1
commit a592b32ca4
3 changed files with 127 additions and 117 deletions

View file

@ -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',

View file

@ -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});
}
}
});

View file

@ -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));