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' => 'c218ed53', - 'core.pkg.js' => '8b7400e7', + 'core.pkg.js' => '0fabde4f', 'darkconsole.pkg.js' => '1f9a31bc', 'differential.pkg.css' => '113e692c', 'differential.pkg.js' => 'f6d809c0', @@ -391,7 +391,7 @@ 'rsrc/js/application/diffusion/behavior-load-blame.js' => '42126667', 'rsrc/js/application/diffusion/behavior-locate-file.js' => '6d3e1947', 'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc', - 'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => 'e5822781', + 'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => '1db13e70', 'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef', 'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab', 'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888', @@ -608,7 +608,7 @@ 'javelin-behavior-diffusion-jump-to' => '73d09eef', 'javelin-behavior-diffusion-locate-file' => '6d3e1947', 'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc', - 'javelin-behavior-doorkeeper-tag' => 'e5822781', + 'javelin-behavior-doorkeeper-tag' => '1db13e70', 'javelin-behavior-drydock-live-operation-status' => '901935ef', 'javelin-behavior-durable-column' => '2ae077e1', 'javelin-behavior-editengine-reorder-configs' => 'd7a74243', @@ -1024,6 +1024,13 @@ 'javelin-request', 'javelin-uri', ), + '1db13e70' => array( + 'javelin-behavior', + 'javelin-dom', + 'javelin-json', + 'javelin-workflow', + 'javelin-magical-init', + ), '1f6794f6' => array( 'javelin-behavior', 'javelin-stratcom', @@ -2087,13 +2094,6 @@ 'javelin-behavior', 'javelin-dom', ), - 'e5822781' => array( - 'javelin-behavior', - 'javelin-dom', - 'javelin-json', - 'javelin-workflow', - 'javelin-magical-init', - ), 'e74b7517' => array( 'javelin-install', 'phuix-button-view', diff --git a/src/applications/doorkeeper/bridge/DoorkeeperBridgeJIRA.php b/src/applications/doorkeeper/bridge/DoorkeeperBridgeJIRA.php --- a/src/applications/doorkeeper/bridge/DoorkeeperBridgeJIRA.php +++ b/src/applications/doorkeeper/bridge/DoorkeeperBridgeJIRA.php @@ -97,6 +97,7 @@ $ref->setAttribute('title', idx($fields, 'summary')); $ref->setAttribute('description', idx($result, 'description')); + $ref->setAttribute('shortname', $result['key']); $obj = $ref->getExternalObject(); if ($obj->getID()) { diff --git a/src/applications/doorkeeper/controller/DoorkeeperTagsController.php b/src/applications/doorkeeper/controller/DoorkeeperTagsController.php --- a/src/applications/doorkeeper/controller/DoorkeeperTagsController.php +++ b/src/applications/doorkeeper/controller/DoorkeeperTagsController.php @@ -13,17 +13,13 @@ } $refs = array(); - $id_map = array(); - foreach ($tags as $tag_spec) { + foreach ($tags as $key => $tag_spec) { $tag = $tag_spec['ref']; $ref = id(new DoorkeeperObjectRef()) ->setApplicationType($tag[0]) ->setApplicationDomain($tag[1]) ->setObjectType($tag[2]) ->setObjectID($tag[3]); - - $key = $ref->getObjectKey(); - $id_map[$key] = $tag_spec['id']; $refs[$key] = $ref; } @@ -43,19 +39,30 @@ continue; } - $id = $id_map[$key]; + $tag_spec = $tags[$key]; + + $id = $tag_spec['id']; + $view = idx($tag_spec, 'view'); + + $is_short = ($view == 'short'); + + if ($is_short) { + $name = $ref->getShortName(); + } else { + $name = $ref->getFullName(); + } $tag = id(new PHUITagView()) ->setID($id) - ->setName($ref->getFullName()) + ->setName($name) ->setHref($uri) ->setType(PHUITagView::TYPE_OBJECT) ->setExternal(true) ->render(); $results[] = array( - 'id' => $id, - 'markup' => $tag, + 'id' => $id, + 'markup' => $tag, ); } diff --git a/src/applications/doorkeeper/engine/DoorkeeperObjectRef.php b/src/applications/doorkeeper/engine/DoorkeeperObjectRef.php --- a/src/applications/doorkeeper/engine/DoorkeeperObjectRef.php +++ b/src/applications/doorkeeper/engine/DoorkeeperObjectRef.php @@ -107,6 +107,13 @@ pht('External Object')); } + public function getShortName() { + return coalesce( + $this->getAttribute('shortname'), + $this->getAttribute('name'), + pht('External Object')); + } + public function getObjectKey() { if (!$this->objectKey) { $this->objectKey = PhabricatorHash::digestForIndex( diff --git a/src/applications/doorkeeper/remarkup/DoorkeeperRemarkupRule.php b/src/applications/doorkeeper/remarkup/DoorkeeperRemarkupRule.php --- a/src/applications/doorkeeper/remarkup/DoorkeeperRemarkupRule.php +++ b/src/applications/doorkeeper/remarkup/DoorkeeperRemarkupRule.php @@ -4,11 +4,41 @@ const KEY_TAGS = 'doorkeeper.tags'; + const VIEW_FULL = 'full'; + const VIEW_SHORT = 'short'; + public function getPriority() { return 350.0; } protected function addDoorkeeperTag(array $spec) { + PhutilTypeSpec::checkMap( + $spec, + array( + 'href' => 'string', + 'tag' => 'map', + + 'name' => 'optional string', + 'view' => 'optional string', + )); + + $spec = $spec + array( + 'view' => self::VIEW_FULL, + ); + + $views = array( + self::VIEW_FULL, + self::VIEW_SHORT, + ); + $views = array_fuse($views); + if (!isset($views[$spec['view']])) { + throw new Exception( + pht( + 'Unsupported Doorkeeper tag view mode "%s". Supported modes are: %s.', + $spec['view'], + implode(', ', $views))); + } + $key = self::KEY_TAGS; $engine = $this->getEngine(); $token = $engine->storeText(get_class($this)); @@ -36,19 +66,26 @@ $refs = array(); foreach ($tags as $spec) { - $tag_id = celerity_generate_unique_node_id(); + $href = $spec['href']; + $name = idx($spec, 'name', $href); - $refs[] = array( - 'id' => $tag_id, - ) + $spec['tag']; + $this->assertFlatText($href); + $this->assertFlatText($name); if ($this->getEngine()->isTextMode()) { - $view = $spec['href']; + $view = "{$name} <{$href}>"; } else { + $tag_id = celerity_generate_unique_node_id(); + + $refs[] = array( + 'id' => $tag_id, + 'view' => $spec['view'], + ) + $spec['tag']; + $view = id(new PHUITagView()) ->setID($tag_id) - ->setName($this->assertFlatText($spec['href'])) - ->setHref($this->assertFlatText($spec['href'])) + ->setName($name) + ->setHref($href) ->setType(PHUITagView::TYPE_OBJECT) ->setExternal(true); } @@ -56,7 +93,9 @@ $engine->overwriteStoredText($spec['token'], $view); } - Javelin::initBehavior('doorkeeper-tag', array('tags' => $refs)); + if ($refs) { + Javelin::initBehavior('doorkeeper-tag', array('tags' => $refs)); + } $engine->setTextMetadata($key, array()); } diff --git a/webroot/rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js b/webroot/rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js --- a/webroot/rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js +++ b/webroot/rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js @@ -40,9 +40,19 @@ }; for (var ii = 0; ii < tags.length; ii++) { - var tag_key = tags[ii].ref.join('@'); + var key_parts = []; + + key_parts = key_parts.concat(tags[ii].ref); + key_parts.push(tags[ii].view); + + var tag_key = key_parts.join(' '); + if (tag_key in statics.cache) { - have.push({id: tags[ii].id, markup: statics.cache[tag_key]}); + have.push( + { + id: tags[ii].id, + markup: statics.cache[tag_key] + }); } else { need.push(tags[ii]); keys[tags[ii].id] = tag_key; @@ -54,7 +64,11 @@ } if (need.length) { - new JX.Workflow('/doorkeeper/tags/', {tags: JX.JSON.stringify(need)}) + var data = { + tags: JX.JSON.stringify(need) + }; + + new JX.Workflow('/doorkeeper/tags/', data) .setHandler(function(r) { draw(r.tags); }) .start(); }