diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -10,7 +10,7 @@ 'conpherence.pkg.css' => 'e68cf1fa', 'conpherence.pkg.js' => '15191c65', 'core.pkg.css' => '2fa91e14', - 'core.pkg.js' => 'e4d73c62', + 'core.pkg.js' => '32bb68e9', 'darkconsole.pkg.js' => '1f9a31bc', 'differential.pkg.css' => '113e692c', 'differential.pkg.js' => 'f6d809c0', @@ -85,7 +85,7 @@ 'rsrc/css/application/maniphest/task-edit.css' => 'fda62a9b', 'rsrc/css/application/maniphest/task-summary.css' => '11cc5344', 'rsrc/css/application/objectselector/object-selector.css' => '85ee8ce6', - 'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b', + 'rsrc/css/application/owners/owners-path-editor.css' => '9c136c29', 'rsrc/css/application/paste/paste.css' => '9fcc9773', 'rsrc/css/application/people/people-picture-menu-item.css' => 'a06f7f34', 'rsrc/css/application/people/people-profile.css' => '4df76faf', @@ -268,7 +268,7 @@ 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js' => '503e17fd', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js' => '013ffff9', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js' => '54f314a0', - 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => '0fcf201c', + 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => 'ab9e0a82', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js' => '6c0e62fa', 'rsrc/favicons/apple-touch-icon-114x114.png' => '12a24178', 'rsrc/favicons/apple-touch-icon-120x120.png' => '0d1543c7', @@ -418,13 +418,13 @@ 'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888', 'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => '191b4909', 'rsrc/js/application/herald/HeraldRuleEditor.js' => 'dca75c0e', - 'rsrc/js/application/herald/PathTypeahead.js' => '78039abe', + 'rsrc/js/application/herald/PathTypeahead.js' => '662e9cea', 'rsrc/js/application/herald/herald-rule-editor.js' => '7ebaeed3', 'rsrc/js/application/maniphest/behavior-batch-selector.js' => 'ad54037e', 'rsrc/js/application/maniphest/behavior-line-chart.js' => 'e4232876', 'rsrc/js/application/maniphest/behavior-list-edit.js' => 'a9f88de2', 'rsrc/js/application/maniphest/behavior-subpriorityeditor.js' => '71237763', - 'rsrc/js/application/owners/OwnersPathEditor.js' => '52b9cbc4', + 'rsrc/js/application/owners/OwnersPathEditor.js' => 'c96502cf', 'rsrc/js/application/owners/owners-path-editor.js' => '7a68dda3', 'rsrc/js/application/passphrase/passphrase-credential-control.js' => '3cb0b2fc', 'rsrc/js/application/pholio/behavior-pholio-mock-edit.js' => 'bee502c8', @@ -534,7 +534,7 @@ 'rsrc/js/phuix/PHUIXButtonView.js' => '8a91e1ac', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => '04b2ae03', 'rsrc/js/phuix/PHUIXExample.js' => '68af71ca', - 'rsrc/js/phuix/PHUIXFormControl.js' => '16ad6224', + 'rsrc/js/phuix/PHUIXFormControl.js' => '210a16c1', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', ), 'symbols' => array( @@ -744,7 +744,7 @@ 'javelin-typeahead-normalizer' => '185bbd53', 'javelin-typeahead-ondemand-source' => '013ffff9', 'javelin-typeahead-preloaded-source' => '54f314a0', - 'javelin-typeahead-source' => '0fcf201c', + 'javelin-typeahead-source' => 'ab9e0a82', 'javelin-typeahead-static-source' => '6c0e62fa', 'javelin-uri' => 'c989ade3', 'javelin-util' => '93cc50d6', @@ -764,10 +764,10 @@ 'maniphest-task-edit-css' => 'fda62a9b', 'maniphest-task-summary-css' => '11cc5344', 'multirow-row-manager' => 'b5d57730', - 'owners-path-editor' => '52b9cbc4', - 'owners-path-editor-css' => '2f00933b', + 'owners-path-editor' => 'c96502cf', + 'owners-path-editor-css' => '9c136c29', 'paste-css' => '9fcc9773', - 'path-typeahead' => '78039abe', + 'path-typeahead' => '662e9cea', 'people-picture-menu-item-css' => 'a06f7f34', 'people-profile-css' => '4df76faf', 'phabricator-action-list-view-css' => '0bcd9a45', @@ -888,7 +888,7 @@ 'phuix-autocomplete' => '7fa5c915', 'phuix-button-view' => '8a91e1ac', 'phuix-dropdown-menu' => '04b2ae03', - 'phuix-form-control-view' => '16ad6224', + 'phuix-form-control-view' => '210a16c1', 'phuix-icon-view' => 'bff6884b', 'policy-css' => '957ea14c', 'policy-edit-css' => '815c66f7', @@ -998,20 +998,10 @@ 'javelin-install', 'javelin-util', ), - '0fcf201c' => array( - 'javelin-install', - 'javelin-util', - 'javelin-dom', - 'javelin-typeahead-normalizer', - ), '15d5ff71' => array( 'aphront-typeahead-control-css', 'phui-tag-view-css', ), - '16ad6224' => array( - 'javelin-install', - 'javelin-dom', - ), '17bb8539' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1061,6 +1051,10 @@ 'javelin-install', 'javelin-dom', ), + '210a16c1' => array( + 'javelin-install', + 'javelin-dom', + ), '2290aeef' => array( 'javelin-install', 'javelin-dom', @@ -1337,14 +1331,6 @@ 'javelin-vector', 'javelin-typeahead-static-source', ), - '52b9cbc4' => array( - 'multirow-row-manager', - 'javelin-install', - 'path-typeahead', - 'javelin-dom', - 'javelin-util', - 'phabricator-prefab', - ), '54b612ba' => array( 'javelin-color', 'javelin-install', @@ -1439,6 +1425,14 @@ 'javelin-workflow', 'javelin-dom', ), + '662e9cea' => array( + 'javelin-install', + 'javelin-typeahead', + 'javelin-dom', + 'javelin-request', + 'javelin-typeahead-ondemand-source', + 'javelin-util', + ), '66a6def1' => array( 'javelin-behavior', 'javelin-dom', @@ -1542,14 +1536,6 @@ 'javelin-request', 'javelin-util', ), - '78039abe' => array( - 'javelin-install', - 'javelin-typeahead', - 'javelin-dom', - 'javelin-request', - 'javelin-typeahead-ondemand-source', - 'javelin-util', - ), '7927a7d3' => array( 'javelin-behavior', 'javelin-quicksand', @@ -1799,6 +1785,12 @@ 'javelin-util', 'phabricator-busy', ), + 'ab9e0a82' => array( + 'javelin-install', + 'javelin-util', + 'javelin-dom', + 'javelin-typeahead-normalizer', + ), 'acd29eee' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1974,6 +1966,15 @@ 'javelin-install', 'javelin-util', ), + 'c96502cf' => array( + 'multirow-row-manager', + 'javelin-install', + 'path-typeahead', + 'javelin-dom', + 'javelin-util', + 'phabricator-prefab', + 'phuix-form-control-view', + ), 'c989ade3' => array( 'javelin-install', 'javelin-util', diff --git a/src/applications/diffusion/controller/DiffusionPathValidateController.php b/src/applications/diffusion/controller/DiffusionPathValidateController.php --- a/src/applications/diffusion/controller/DiffusionPathValidateController.php +++ b/src/applications/diffusion/controller/DiffusionPathValidateController.php @@ -45,19 +45,6 @@ 'valid' => (bool)$valid, ); - if (!$valid) { - $branch = $drequest->getBranch(); - if ($branch) { - $message = pht('Not found in %s', $branch); - } else { - $message = pht('Not found at %s', 'HEAD'); - } - } else { - $message = pht('OK'); - } - - $output['message'] = $message; - return id(new AphrontAjaxResponse())->setContent($output); } } diff --git a/src/applications/owners/controller/PhabricatorOwnersPathsController.php b/src/applications/owners/controller/PhabricatorOwnersPathsController.php --- a/src/applications/owners/controller/PhabricatorOwnersPathsController.php +++ b/src/applications/owners/controller/PhabricatorOwnersPathsController.php @@ -27,7 +27,7 @@ $path_refs = array(); foreach ($paths as $key => $path) { - if (!isset($repos[$key])) { + if (!isset($repos[$key]) || !strlen($repos[$key])) { throw new Exception( pht( 'No repository PHID for path "%s"!', @@ -70,17 +70,39 @@ $path_refs = mpull($paths, 'getRef'); } - $repos = id(new PhabricatorRepositoryQuery()) - ->setViewer($viewer) - ->execute(); + $template = new AphrontTokenizerTemplateView(); + + $datasource = id(new DiffusionRepositoryDatasource()) + ->setViewer($viewer); - $repo_map = array(); - foreach ($repos as $key => $repo) { - $monogram = $repo->getMonogram(); - $name = $repo->getName(); - $repo_map[$repo->getPHID()] = "{$monogram} {$name}"; + $tokenizer_spec = array( + 'markup' => $template->render(), + 'config' => array( + 'src' => $datasource->getDatasourceURI(), + 'browseURI' => $datasource->getBrowseURI(), + 'placeholder' => $datasource->getPlaceholderText(), + 'limit' => 1, + ), + ); + + foreach ($path_refs as $key => $path_ref) { + $path_refs[$key]['repositoryValue'] = $datasource->getWireTokens( + array( + $path_ref['repositoryPHID'], + )); } - asort($repos); + + $icon_test = id(new PHUIIconView()) + ->setIcon('fa-spinner grey') + ->setTooltip(pht('Validating...')); + + $icon_okay = id(new PHUIIconView()) + ->setIcon('fa-check-circle green') + ->setTooltip(pht('Path Exists in Repository')); + + $icon_fail = id(new PHUIIconView()) + ->setIcon('fa-question-circle-o red') + ->setTooltip(pht('Path Not Found On Default Branch')); $template = new AphrontTypeaheadTemplateView(); $template = $template->render(); @@ -88,15 +110,23 @@ Javelin::initBehavior( 'owners-path-editor', array( - 'root' => 'path-editor', - 'table' => 'paths', - 'add_button' => 'addpath', - 'repositories' => $repo_map, - 'input_template' => $template, - 'pathRefs' => $path_refs, - - 'completeURI' => '/diffusion/services/path/complete/', - 'validateURI' => '/diffusion/services/path/validate/', + 'root' => 'path-editor', + 'table' => 'paths', + 'add_button' => 'addpath', + 'input_template' => $template, + 'pathRefs' => $path_refs, + 'completeURI' => '/diffusion/services/path/complete/', + 'validateURI' => '/diffusion/services/path/validate/', + 'repositoryTokenizerSpec' => $tokenizer_spec, + 'icons' => array( + 'test' => hsprintf('%s', $icon_test), + 'okay' => hsprintf('%s', $icon_okay), + 'fail' => hsprintf('%s', $icon_fail), + ), + 'modeOptions' => array( + 0 => pht('Include'), + 1 => pht('Exclude'), + ), )); require_celerity_resource('owners-path-editor-css'); diff --git a/webroot/rsrc/css/application/owners/owners-path-editor.css b/webroot/rsrc/css/application/owners/owners-path-editor.css --- a/webroot/rsrc/css/application/owners/owners-path-editor.css +++ b/webroot/rsrc/css/application/owners/owners-path-editor.css @@ -3,7 +3,8 @@ */ .owners-path-editor-table { - margin: 10px; + margin: 10px 0; + width: 100%; } .owners-path-editor-table td { @@ -11,27 +12,38 @@ vertical-align: middle; } -.owners-path-editor-table select.owners-repo { - width: 150px; +.owners-path-editor-table td.owners-path-mode-control { + width: 180px; } -.owners-path-editor-table input { - width: 400px; +.owners-path-editor-table td.owners-path-mode-control select { + width: 100%; } -.owners-path-editor-table div.error-display { - padding: 4px 12px 0; +.owners-path-editor-table td.owners-path-repo-control { + width: 280px; } -.owners-path-editor-table div.validating { - color: {$greytext}; +.owners-path-editor-table td.owners-path-path-control { + width: auto; } -.owners-path-editor-table div.invalid { - color: #aa0000; +.owners-path-editor-table td.owners-path-path-control input { + width: 100%; } -.owners-path-editor-table div.valid { - color: #00aa00; - font-weight: bold; +.owners-path-editor-table td.owners-path-path-control .jx-typeahead-results a { + padding: 4px; +} + +.owners-path-editor-table td.owners-path-icon-control { + width: 18px; +} + +.owners-path-editor-table td.remove-column { + width: 100px; +} + +.owners-path-editor-table td.remove-column a { + display: block; } diff --git a/webroot/rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js b/webroot/rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js --- a/webroot/rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js +++ b/webroot/rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js @@ -9,8 +9,7 @@ JX.install('TypeaheadSource', { construct : function() { - this._raw = {}; - this._lookup = {}; + this.resetResults(); this.setNormalizer(JX.TypeaheadNormalizer.normalize); this._excludeIDs = {}; }, @@ -359,6 +358,12 @@ } return str.split(/\s+/g); }, + + resetResults: function() { + this._raw = {}; + this._lookup = {}; + }, + _defaultTransformer : function(object) { return { name : object[0], diff --git a/webroot/rsrc/js/application/herald/PathTypeahead.js b/webroot/rsrc/js/application/herald/PathTypeahead.js --- a/webroot/rsrc/js/application/herald/PathTypeahead.js +++ b/webroot/rsrc/js/application/herald/PathTypeahead.js @@ -11,7 +11,7 @@ JX.install('PathTypeahead', { construct : function(config) { - this._repositorySelect = config.repo_select; + this._repositoryTokenizer = config.repositoryTokenizer; this._hardpoint = config.hardpoint; this._input = config.path_input; this._completeURI = config.completeURI; @@ -19,14 +19,14 @@ this._errorDisplay = config.error_display; this._textInputValues = {}; + this._icons = config.icons; + this._initializeDatasource(); this._initializeTypeahead(this._input); }, members : { - /* - * DOM