1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-05 03:18:25 +01:00

Make browse action available for dynamic/JS-driven tokenizers

Summary: Ref T5750. This makes browse work for all of the dynamic tokenizers in Herald, Policies, batch editor, etc.

Test Plan: Used tokenizers in Herald, Policies, Batch editor.

Reviewers: chad, btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T5750

Differential Revision: https://secure.phabricator.com/D12442
This commit is contained in:
epriestley 2015-04-16 14:46:10 -07:00
parent a641601407
commit a4261f41c2
14 changed files with 95 additions and 78 deletions

View file

@ -605,9 +605,12 @@ final class HeraldRuleController extends HeraldController {
);
foreach ($sources as $key => $source) {
$source->setViewer($this->getViewer());
$sources[$key] = array(
'uri' => $source->getDatasourceURI(),
'placeholder' => $source->getPlaceholderText(),
'browseURI' => $source->getBrowseURI(),
);
}

View file

@ -3,11 +3,6 @@
final class PhabricatorMailingListDatasource
extends PhabricatorTypeaheadDatasource {
public function isBrowsable() {
// TODO: Make this browsable if we don't delete it before then.
return false;
}
public function getPlaceholderText() {
return pht('Type a mailing list name...');
}
@ -20,11 +15,10 @@ final class PhabricatorMailingListDatasource
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$results = array();
$query = id(new PhabricatorMailingListQuery());
$lists = $this->executeQuery($query);
$lists = id(new PhabricatorMailingListQuery())
->setViewer($viewer)
->execute();
$results = array();
foreach ($lists as $list) {
$results[] = id(new PhabricatorTypeaheadResult())
->setName($list->getName())
@ -32,7 +26,10 @@ final class PhabricatorMailingListDatasource
->setPHID($list->getPHID());
}
return $results;
// TODO: It would be slightly preferable to do this as part of the query,
// this is just simpler for the moment.
return $this->filterResultsAgainstTokens($results);
}
}

View file

@ -65,7 +65,9 @@ final class ManiphestBatchEditController extends ManiphestController {
$projects_source = new PhabricatorProjectDatasource();
$mailable_source = new PhabricatorMetaMTAMailableDatasource();
$mailable_source->setViewer($user);
$owner_source = new PhabricatorTypeaheadOwnerDatasource();
$owner_source->setViewer($user);
require_celerity_resource('maniphest-batch-editor');
Javelin::initBehavior(
@ -75,17 +77,20 @@ final class ManiphestBatchEditController extends ManiphestController {
'tokenizerTemplate' => $template,
'sources' => array(
'project' => array(
'src' => $projects_source->getDatasourceURI(),
'placeholder' => $projects_source->getPlaceholderText(),
'src' => $projects_source->getDatasourceURI(),
'placeholder' => $projects_source->getPlaceholderText(),
'browseURI' => $projects_source->getBrowseURI(),
),
'owner' => array(
'src' => $owner_source->getDatasourceURI(),
'placeholder' => $owner_source->getPlaceholderText(),
'limit' => 1,
'src' => $owner_source->getDatasourceURI(),
'placeholder' => $owner_source->getPlaceholderText(),
'browseURI' => $owner_source->getBrowseURI(),
'limit' => 1,
),
'cc' => array(
'src' => $mailable_source->getDatasourceURI(),
'placeholder' => $mailable_source->getPlaceholderText(),
'cc' => array(
'src' => $mailable_source->getDatasourceURI(),
'placeholder' => $mailable_source->getPlaceholderText(),
'browseURI' => $mailable_source->getBrowseURI(),
),
),
'input' => 'batch-form-actions',

View file

@ -40,13 +40,7 @@ final class PhabricatorLegalpadSignaturePolicyRule
}
public function getValueControlTemplate() {
$datasource = new LegalpadDocumentDatasource();
return array(
'markup' => new AphrontTokenizerTemplateView(),
'uri' => $datasource->getDatasourceURI(),
'placeholder' => $datasource->getPlaceholderText(),
);
return $this->getDatasourceTemplate(new LegalpadDocumentDatasource());
}
public function getRuleOrder() {

View file

@ -22,6 +22,16 @@ abstract class PhabricatorPolicyRule {
return null;
}
protected function getDatasourceTemplate(
PhabricatorTypeaheadDatasource $datasource) {
return array(
'markup' => new AphrontTokenizerTemplateView(),
'uri' => $datasource->getDatasourceURI(),
'placeholder' => $datasource->getPlaceholderText(),
'browseURI' => $datasource->getBrowseURI(),
);
}
public function getRuleOrder() {
return 500;
}

View file

@ -38,13 +38,7 @@ final class PhabricatorProjectsPolicyRule extends PhabricatorPolicyRule {
}
public function getValueControlTemplate() {
$projects_source = new PhabricatorProjectDatasource();
return array(
'markup' => new AphrontTokenizerTemplateView(),
'uri' => $projects_source->getDatasourceURI(),
'placeholder' => $projects_source->getPlaceholderText(),
);
return $this->getDatasourceTemplate(new PhabricatorProjectDatasource());
}
public function getRuleOrder() {

View file

@ -20,13 +20,7 @@ final class PhabricatorUsersPolicyRule extends PhabricatorPolicyRule {
}
public function getValueControlTemplate() {
$users_datasource = new PhabricatorPeopleDatasource();
return array(
'markup' => new AphrontTokenizerTemplateView(),
'uri' => $users_datasource->getDatasourceURI(),
'placeholder' => $users_datasource->getPlaceholderText(),
);
return $this->getDatasourceTemplate(new PhabricatorPeopleDatasource());
}
public function getRuleOrder() {

View file

@ -67,35 +67,40 @@ final class AphrontTokenizerTemplateView extends AphrontView {
$content[] = $input;
$content[] = phutil_tag('div', array('style' => 'clear: both;'), '');
$container = phutil_tag(
$container = javelin_tag(
'div',
array(
'id' => $id,
'class' => 'jx-tokenizer-container',
'sigil' => 'tokenizer-container',
),
$content);
$browse = null;
if ($this->browseURI) {
$icon = id(new PHUIIconView())
->setIconFont('fa-list-ul');
$icon = id(new PHUIIconView())
->setIconFont('fa-list-ul');
// TODO: This thing is ugly and the ugliness is not intentional.
// We have to give it text or PHUIButtonView collapses. It should likely
// just be an icon and look more integrated into the input.
$browse = id(new PHUIButtonView())
->setTag('a')
->setIcon($icon)
->addSigil('tokenizer-browse')
->setColor(PHUIButtonView::GREY)
->setSize(PHUIButtonView::SMALL)
->setText(pht('Browse...'));
// TODO: This thing is ugly and the ugliness is not intentional.
// We have to give it text or PHUIButtonView collapses. It should likely
// just be an icon and look more integrated into the input.
$browse = id(new PHUIButtonView())
->setTag('a')
->setIcon($icon)
->addSigil('tokenizer-browse')
->setColor(PHUIButtonView::GREY)
->setSize(PHUIButtonView::SMALL)
->setText(pht('Browse...'));
$classes = array();
$classes[] = 'jx-tokenizer-frame';
if ($this->browseURI) {
$classes[] = 'has-browse';
}
$frame = javelin_tag(
'table',
array(
'class' => 'jx-tokenizer-frame',
'class' => implode(' ', $classes),
'sigil' => 'tokenizer-frame',
),
phutil_tag(

View file

@ -109,7 +109,15 @@ a.jx-tokenizer-token:hover {
width: 100%;
}
.jx-tokenizer-frame-input {
.jx-tokenizer-frame .jx-tokenizer-frame-browse {
display: none;
}
.has-browse .jx-tokenizer-frame-browse {
display: table-cell;
}
.jx-tokenizer-frame td.jx-tokenizer-frame-input {
width: 100%;
}

View file

@ -85,6 +85,7 @@ JX.install('Tokenizer', {
}
if (this._frame) {
JX.DOM.alterClass(this._frame, 'has-browse', !!this.getBrowseURI());
JX.DOM.listen(
this._frame,
'click',

View file

@ -277,25 +277,21 @@ JX.install('HeraldRuleEditor', {
},
_newTokenizer : function(type) {
var template = JX.$N(
'div',
JX.$H(this._config.template.markup));
template = template.firstChild;
template.id = '';
var tokenizerConfig = {
root : template,
src : this._config.template.source[type].uri,
placeholder: this._config.template.source[type].placeholder,
browseURI: this._config.template.source[type].browseURI,
icons : this._config.template.icons,
username : this._config.username
};
var build = JX.Prefab.buildTokenizer(tokenizerConfig);
var build = JX.Prefab.newTokenizerFromTemplate(
this._config.template.markup,
tokenizerConfig);
build.tokenizer.start();
return [
template,
build.node,
function() {
return build.tokenizer.getTokens();
},

View file

@ -136,18 +136,14 @@ JX.behavior('maniphest-batch-editor', function(config) {
});
function build_tokenizer(tconfig) {
var template = JX.$N('div', JX.$H(config.tokenizerTemplate)).firstChild;
template.id = '';
var build_config = JX.copy({}, tconfig);
build_config.root = template;
var built = JX.Prefab.buildTokenizer(build_config);
var built = JX.Prefab.newTokenizerFromTemplate(
config.tokenizerTemplate,
JX.copy({}, tconfig));
built.tokenizer.start();
return {
object: built.tokenizer,
template: template
template: built.node
};
}

View file

@ -118,17 +118,20 @@ JX.behavior('policy-rule-editor', function(config) {
switch (type) {
case 'tokenizer':
node = JX.$H(template.markup).getNode();
node.id = '';
var options = {
root: node,
src: template.uri,
placeholder: template.placeholder,
browseURI: template.browseURI,
limit: template.limit
};
var tokenizer = JX.Prefab.buildTokenizer(options).tokenizer;
var build = JX.Prefab.newTokenizerFromTemplate(
template.markup,
options);
node = build.node;
var tokenizer = build.tokenizer;
tokenizer.start();
get_fn = function() { return JX.keys(tokenizer.getTokens()); };

View file

@ -31,6 +31,17 @@ JX.install('Prefab', {
return select;
},
newTokenizerFromTemplate: function(markup, config) {
var template = JX.$H(markup).getFragment().firstChild;
var container = JX.DOM.find(template, 'div', 'tokenizer-container');
container.id = '';
config.root = container;
var build = JX.Prefab.buildTokenizer(config);
build.node = template;
return build;
},
/**
* Build a Phabricator tokenizer out of a configuration with application