@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+95 -78
+3
src/applications/herald/controller/HeraldRuleController.php
··· 605 605 ); 606 606 607 607 foreach ($sources as $key => $source) { 608 + $source->setViewer($this->getViewer()); 609 + 608 610 $sources[$key] = array( 609 611 'uri' => $source->getDatasourceURI(), 610 612 'placeholder' => $source->getPlaceholderText(), 613 + 'browseURI' => $source->getBrowseURI(), 611 614 ); 612 615 } 613 616
+7 -10
src/applications/mailinglists/typeahead/PhabricatorMailingListDatasource.php
··· 3 3 final class PhabricatorMailingListDatasource 4 4 extends PhabricatorTypeaheadDatasource { 5 5 6 - public function isBrowsable() { 7 - // TODO: Make this browsable if we don't delete it before then. 8 - return false; 9 - } 10 - 11 6 public function getPlaceholderText() { 12 7 return pht('Type a mailing list name...'); 13 8 } ··· 20 15 $viewer = $this->getViewer(); 21 16 $raw_query = $this->getRawQuery(); 22 17 23 - $results = array(); 18 + $query = id(new PhabricatorMailingListQuery()); 19 + $lists = $this->executeQuery($query); 24 20 25 - $lists = id(new PhabricatorMailingListQuery()) 26 - ->setViewer($viewer) 27 - ->execute(); 21 + $results = array(); 28 22 foreach ($lists as $list) { 29 23 $results[] = id(new PhabricatorTypeaheadResult()) 30 24 ->setName($list->getName()) ··· 32 26 ->setPHID($list->getPHID()); 33 27 } 34 28 35 - return $results; 29 + // TODO: It would be slightly preferable to do this as part of the query, 30 + // this is just simpler for the moment. 31 + 32 + return $this->filterResultsAgainstTokens($results); 36 33 } 37 34 38 35 }
+13 -8
src/applications/maniphest/controller/ManiphestBatchEditController.php
··· 65 65 66 66 $projects_source = new PhabricatorProjectDatasource(); 67 67 $mailable_source = new PhabricatorMetaMTAMailableDatasource(); 68 + $mailable_source->setViewer($user); 68 69 $owner_source = new PhabricatorTypeaheadOwnerDatasource(); 70 + $owner_source->setViewer($user); 69 71 70 72 require_celerity_resource('maniphest-batch-editor'); 71 73 Javelin::initBehavior( ··· 75 77 'tokenizerTemplate' => $template, 76 78 'sources' => array( 77 79 'project' => array( 78 - 'src' => $projects_source->getDatasourceURI(), 79 - 'placeholder' => $projects_source->getPlaceholderText(), 80 + 'src' => $projects_source->getDatasourceURI(), 81 + 'placeholder' => $projects_source->getPlaceholderText(), 82 + 'browseURI' => $projects_source->getBrowseURI(), 80 83 ), 81 84 'owner' => array( 82 - 'src' => $owner_source->getDatasourceURI(), 83 - 'placeholder' => $owner_source->getPlaceholderText(), 84 - 'limit' => 1, 85 + 'src' => $owner_source->getDatasourceURI(), 86 + 'placeholder' => $owner_source->getPlaceholderText(), 87 + 'browseURI' => $owner_source->getBrowseURI(), 88 + 'limit' => 1, 85 89 ), 86 - 'cc' => array( 87 - 'src' => $mailable_source->getDatasourceURI(), 88 - 'placeholder' => $mailable_source->getPlaceholderText(), 90 + 'cc' => array( 91 + 'src' => $mailable_source->getDatasourceURI(), 92 + 'placeholder' => $mailable_source->getPlaceholderText(), 93 + 'browseURI' => $mailable_source->getBrowseURI(), 89 94 ), 90 95 ), 91 96 'input' => 'batch-form-actions',
+1 -7
src/applications/policy/rule/PhabricatorLegalpadSignaturePolicyRule.php
··· 40 40 } 41 41 42 42 public function getValueControlTemplate() { 43 - $datasource = new LegalpadDocumentDatasource(); 44 - 45 - return array( 46 - 'markup' => new AphrontTokenizerTemplateView(), 47 - 'uri' => $datasource->getDatasourceURI(), 48 - 'placeholder' => $datasource->getPlaceholderText(), 49 - ); 43 + return $this->getDatasourceTemplate(new LegalpadDocumentDatasource()); 50 44 } 51 45 52 46 public function getRuleOrder() {
+10
src/applications/policy/rule/PhabricatorPolicyRule.php
··· 22 22 return null; 23 23 } 24 24 25 + protected function getDatasourceTemplate( 26 + PhabricatorTypeaheadDatasource $datasource) { 27 + return array( 28 + 'markup' => new AphrontTokenizerTemplateView(), 29 + 'uri' => $datasource->getDatasourceURI(), 30 + 'placeholder' => $datasource->getPlaceholderText(), 31 + 'browseURI' => $datasource->getBrowseURI(), 32 + ); 33 + } 34 + 25 35 public function getRuleOrder() { 26 36 return 500; 27 37 }
+1 -7
src/applications/policy/rule/PhabricatorProjectsPolicyRule.php
··· 38 38 } 39 39 40 40 public function getValueControlTemplate() { 41 - $projects_source = new PhabricatorProjectDatasource(); 42 - 43 - return array( 44 - 'markup' => new AphrontTokenizerTemplateView(), 45 - 'uri' => $projects_source->getDatasourceURI(), 46 - 'placeholder' => $projects_source->getPlaceholderText(), 47 - ); 41 + return $this->getDatasourceTemplate(new PhabricatorProjectDatasource()); 48 42 } 49 43 50 44 public function getRuleOrder() {
+1 -7
src/applications/policy/rule/PhabricatorUsersPolicyRule.php
··· 20 20 } 21 21 22 22 public function getValueControlTemplate() { 23 - $users_datasource = new PhabricatorPeopleDatasource(); 24 - 25 - return array( 26 - 'markup' => new AphrontTokenizerTemplateView(), 27 - 'uri' => $users_datasource->getDatasourceURI(), 28 - 'placeholder' => $users_datasource->getPlaceholderText(), 29 - ); 23 + return $this->getDatasourceTemplate(new PhabricatorPeopleDatasource()); 30 24 } 31 25 32 26 public function getRuleOrder() {
+21 -16
src/view/control/AphrontTokenizerTemplateView.php
··· 67 67 $content[] = $input; 68 68 $content[] = phutil_tag('div', array('style' => 'clear: both;'), ''); 69 69 70 - $container = phutil_tag( 70 + $container = javelin_tag( 71 71 'div', 72 72 array( 73 73 'id' => $id, 74 74 'class' => 'jx-tokenizer-container', 75 + 'sigil' => 'tokenizer-container', 75 76 ), 76 77 $content); 77 78 78 - $browse = null; 79 - if ($this->browseURI) { 80 - $icon = id(new PHUIIconView()) 81 - ->setIconFont('fa-list-ul'); 79 + $icon = id(new PHUIIconView()) 80 + ->setIconFont('fa-list-ul'); 81 + 82 + // TODO: This thing is ugly and the ugliness is not intentional. 83 + // We have to give it text or PHUIButtonView collapses. It should likely 84 + // just be an icon and look more integrated into the input. 85 + $browse = id(new PHUIButtonView()) 86 + ->setTag('a') 87 + ->setIcon($icon) 88 + ->addSigil('tokenizer-browse') 89 + ->setColor(PHUIButtonView::GREY) 90 + ->setSize(PHUIButtonView::SMALL) 91 + ->setText(pht('Browse...')); 92 + 93 + $classes = array(); 94 + $classes[] = 'jx-tokenizer-frame'; 82 95 83 - // TODO: This thing is ugly and the ugliness is not intentional. 84 - // We have to give it text or PHUIButtonView collapses. It should likely 85 - // just be an icon and look more integrated into the input. 86 - $browse = id(new PHUIButtonView()) 87 - ->setTag('a') 88 - ->setIcon($icon) 89 - ->addSigil('tokenizer-browse') 90 - ->setColor(PHUIButtonView::GREY) 91 - ->setSize(PHUIButtonView::SMALL) 92 - ->setText(pht('Browse...')); 96 + if ($this->browseURI) { 97 + $classes[] = 'has-browse'; 93 98 } 94 99 95 100 $frame = javelin_tag( 96 101 'table', 97 102 array( 98 - 'class' => 'jx-tokenizer-frame', 103 + 'class' => implode(' ', $classes), 99 104 'sigil' => 'tokenizer-frame', 100 105 ), 101 106 phutil_tag(
+9 -1
webroot/rsrc/css/aphront/tokenizer.css
··· 109 109 width: 100%; 110 110 } 111 111 112 - .jx-tokenizer-frame-input { 112 + .jx-tokenizer-frame .jx-tokenizer-frame-browse { 113 + display: none; 114 + } 115 + 116 + .has-browse .jx-tokenizer-frame-browse { 117 + display: table-cell; 118 + } 119 + 120 + .jx-tokenizer-frame td.jx-tokenizer-frame-input { 113 121 width: 100%; 114 122 } 115 123
+1
webroot/rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js
··· 85 85 } 86 86 87 87 if (this._frame) { 88 + JX.DOM.alterClass(this._frame, 'has-browse', !!this.getBrowseURI()); 88 89 JX.DOM.listen( 89 90 this._frame, 90 91 'click',
+5 -9
webroot/rsrc/js/application/herald/HeraldRuleEditor.js
··· 277 277 }, 278 278 279 279 _newTokenizer : function(type) { 280 - var template = JX.$N( 281 - 'div', 282 - JX.$H(this._config.template.markup)); 283 - template = template.firstChild; 284 - template.id = ''; 285 - 286 280 var tokenizerConfig = { 287 - root : template, 288 281 src : this._config.template.source[type].uri, 289 282 placeholder: this._config.template.source[type].placeholder, 283 + browseURI: this._config.template.source[type].browseURI, 290 284 icons : this._config.template.icons, 291 285 username : this._config.username 292 286 }; 293 287 294 - var build = JX.Prefab.buildTokenizer(tokenizerConfig); 288 + var build = JX.Prefab.newTokenizerFromTemplate( 289 + this._config.template.markup, 290 + tokenizerConfig); 295 291 build.tokenizer.start(); 296 292 297 293 return [ 298 - template, 294 + build.node, 299 295 function() { 300 296 return build.tokenizer.getTokens(); 301 297 },
+4 -8
webroot/rsrc/js/application/maniphest/behavior-batch-editor.js
··· 136 136 }); 137 137 138 138 function build_tokenizer(tconfig) { 139 - var template = JX.$N('div', JX.$H(config.tokenizerTemplate)).firstChild; 140 - template.id = ''; 141 - 142 - var build_config = JX.copy({}, tconfig); 143 - build_config.root = template; 144 - 145 - var built = JX.Prefab.buildTokenizer(build_config); 139 + var built = JX.Prefab.newTokenizerFromTemplate( 140 + config.tokenizerTemplate, 141 + JX.copy({}, tconfig)); 146 142 built.tokenizer.start(); 147 143 148 144 return { 149 145 object: built.tokenizer, 150 - template: template 146 + template: built.node 151 147 }; 152 148 } 153 149
+8 -5
webroot/rsrc/js/application/policy/behavior-policy-rule-editor.js
··· 118 118 119 119 switch (type) { 120 120 case 'tokenizer': 121 - node = JX.$H(template.markup).getNode(); 122 - node.id = ''; 123 - 124 121 var options = { 125 - root: node, 126 122 src: template.uri, 127 123 placeholder: template.placeholder, 124 + browseURI: template.browseURI, 128 125 limit: template.limit 129 126 }; 130 127 131 - var tokenizer = JX.Prefab.buildTokenizer(options).tokenizer; 128 + var build = JX.Prefab.newTokenizerFromTemplate( 129 + template.markup, 130 + options); 131 + 132 + node = build.node; 133 + 134 + var tokenizer = build.tokenizer; 132 135 tokenizer.start(); 133 136 134 137 get_fn = function() { return JX.keys(tokenizer.getTokens()); };
+11
webroot/rsrc/js/core/Prefab.js
··· 31 31 return select; 32 32 }, 33 33 34 + newTokenizerFromTemplate: function(markup, config) { 35 + var template = JX.$H(markup).getFragment().firstChild; 36 + var container = JX.DOM.find(template, 'div', 'tokenizer-container'); 37 + 38 + container.id = ''; 39 + config.root = container; 40 + 41 + var build = JX.Prefab.buildTokenizer(config); 42 + build.node = template; 43 + return build; 44 + }, 34 45 35 46 /** 36 47 * Build a Phabricator tokenizer out of a configuration with application