mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-01 19:22:42 +01:00
Allow Doorkeeper references to have multiple display variations (full, short, etc.)
Summary: Ref T13102. An install has a custom rule for bridging JIRA references via Doorkeeper and would like to be able to render them as `JIRA-123` instead of `JIRA JIRA-123 Full JIRA title`. I think it's reasonable to imagine future support upstream for `JIRA-123`, `{JIRA-123}`, and so on, although we do not support these today. We can take a small step toward eventual support by letting the rendering pipeline understand different view modes. This adds an optional `name` (the default text rendered before we do the OAuth sync) and an optional `view`, which can be `short` or `full`. Test Plan: I tested this primarily with Asana, since it's less of a pain to set up than JIRA. The logic should be similar, hopefully. I changed `DoorkeeperAsanaRemarkupRule` to specify `name` and `view`, e.g `'view' => (mt_rand(0, 1) ? 'short' : 'full')`. Then I made a bunch of Asana references in a comment and saw them randomly go short or long. Maniphest Tasks: T13102 Differential Revision: https://secure.phabricator.com/D19215
This commit is contained in:
parent
a4a390fe2d
commit
2b19f91936
6 changed files with 98 additions and 30 deletions
|
@ -10,7 +10,7 @@ return array(
|
||||||
'conpherence.pkg.css' => 'e68cf1fa',
|
'conpherence.pkg.css' => 'e68cf1fa',
|
||||||
'conpherence.pkg.js' => '15191c65',
|
'conpherence.pkg.js' => '15191c65',
|
||||||
'core.pkg.css' => 'c218ed53',
|
'core.pkg.css' => 'c218ed53',
|
||||||
'core.pkg.js' => '8b7400e7',
|
'core.pkg.js' => '0fabde4f',
|
||||||
'darkconsole.pkg.js' => '1f9a31bc',
|
'darkconsole.pkg.js' => '1f9a31bc',
|
||||||
'differential.pkg.css' => '113e692c',
|
'differential.pkg.css' => '113e692c',
|
||||||
'differential.pkg.js' => 'f6d809c0',
|
'differential.pkg.js' => 'f6d809c0',
|
||||||
|
@ -391,7 +391,7 @@ return array(
|
||||||
'rsrc/js/application/diffusion/behavior-load-blame.js' => '42126667',
|
'rsrc/js/application/diffusion/behavior-load-blame.js' => '42126667',
|
||||||
'rsrc/js/application/diffusion/behavior-locate-file.js' => '6d3e1947',
|
'rsrc/js/application/diffusion/behavior-locate-file.js' => '6d3e1947',
|
||||||
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc',
|
'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/drydock/drydock-live-operation-status.js' => '901935ef',
|
||||||
'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab',
|
'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab',
|
||||||
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888',
|
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888',
|
||||||
|
@ -608,7 +608,7 @@ return array(
|
||||||
'javelin-behavior-diffusion-jump-to' => '73d09eef',
|
'javelin-behavior-diffusion-jump-to' => '73d09eef',
|
||||||
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
|
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
|
||||||
'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc',
|
'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-drydock-live-operation-status' => '901935ef',
|
||||||
'javelin-behavior-durable-column' => '2ae077e1',
|
'javelin-behavior-durable-column' => '2ae077e1',
|
||||||
'javelin-behavior-editengine-reorder-configs' => 'd7a74243',
|
'javelin-behavior-editengine-reorder-configs' => 'd7a74243',
|
||||||
|
@ -1024,6 +1024,13 @@ return array(
|
||||||
'javelin-request',
|
'javelin-request',
|
||||||
'javelin-uri',
|
'javelin-uri',
|
||||||
),
|
),
|
||||||
|
'1db13e70' => array(
|
||||||
|
'javelin-behavior',
|
||||||
|
'javelin-dom',
|
||||||
|
'javelin-json',
|
||||||
|
'javelin-workflow',
|
||||||
|
'javelin-magical-init',
|
||||||
|
),
|
||||||
'1f6794f6' => array(
|
'1f6794f6' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
|
@ -2087,13 +2094,6 @@ return array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
),
|
),
|
||||||
'e5822781' => array(
|
|
||||||
'javelin-behavior',
|
|
||||||
'javelin-dom',
|
|
||||||
'javelin-json',
|
|
||||||
'javelin-workflow',
|
|
||||||
'javelin-magical-init',
|
|
||||||
),
|
|
||||||
'e74b7517' => array(
|
'e74b7517' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
'phuix-button-view',
|
'phuix-button-view',
|
||||||
|
|
|
@ -97,6 +97,7 @@ final class DoorkeeperBridgeJIRA extends DoorkeeperBridge {
|
||||||
|
|
||||||
$ref->setAttribute('title', idx($fields, 'summary'));
|
$ref->setAttribute('title', idx($fields, 'summary'));
|
||||||
$ref->setAttribute('description', idx($result, 'description'));
|
$ref->setAttribute('description', idx($result, 'description'));
|
||||||
|
$ref->setAttribute('shortname', $result['key']);
|
||||||
|
|
||||||
$obj = $ref->getExternalObject();
|
$obj = $ref->getExternalObject();
|
||||||
if ($obj->getID()) {
|
if ($obj->getID()) {
|
||||||
|
|
|
@ -13,17 +13,13 @@ final class DoorkeeperTagsController extends PhabricatorController {
|
||||||
}
|
}
|
||||||
|
|
||||||
$refs = array();
|
$refs = array();
|
||||||
$id_map = array();
|
foreach ($tags as $key => $tag_spec) {
|
||||||
foreach ($tags as $tag_spec) {
|
|
||||||
$tag = $tag_spec['ref'];
|
$tag = $tag_spec['ref'];
|
||||||
$ref = id(new DoorkeeperObjectRef())
|
$ref = id(new DoorkeeperObjectRef())
|
||||||
->setApplicationType($tag[0])
|
->setApplicationType($tag[0])
|
||||||
->setApplicationDomain($tag[1])
|
->setApplicationDomain($tag[1])
|
||||||
->setObjectType($tag[2])
|
->setObjectType($tag[2])
|
||||||
->setObjectID($tag[3]);
|
->setObjectID($tag[3]);
|
||||||
|
|
||||||
$key = $ref->getObjectKey();
|
|
||||||
$id_map[$key] = $tag_spec['id'];
|
|
||||||
$refs[$key] = $ref;
|
$refs[$key] = $ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,11 +39,22 @@ final class DoorkeeperTagsController extends PhabricatorController {
|
||||||
continue;
|
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())
|
$tag = id(new PHUITagView())
|
||||||
->setID($id)
|
->setID($id)
|
||||||
->setName($ref->getFullName())
|
->setName($name)
|
||||||
->setHref($uri)
|
->setHref($uri)
|
||||||
->setType(PHUITagView::TYPE_OBJECT)
|
->setType(PHUITagView::TYPE_OBJECT)
|
||||||
->setExternal(true)
|
->setExternal(true)
|
||||||
|
|
|
@ -107,6 +107,13 @@ final class DoorkeeperObjectRef extends Phobject {
|
||||||
pht('External Object'));
|
pht('External Object'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getShortName() {
|
||||||
|
return coalesce(
|
||||||
|
$this->getAttribute('shortname'),
|
||||||
|
$this->getAttribute('name'),
|
||||||
|
pht('External Object'));
|
||||||
|
}
|
||||||
|
|
||||||
public function getObjectKey() {
|
public function getObjectKey() {
|
||||||
if (!$this->objectKey) {
|
if (!$this->objectKey) {
|
||||||
$this->objectKey = PhabricatorHash::digestForIndex(
|
$this->objectKey = PhabricatorHash::digestForIndex(
|
||||||
|
|
|
@ -4,11 +4,41 @@ abstract class DoorkeeperRemarkupRule extends PhutilRemarkupRule {
|
||||||
|
|
||||||
const KEY_TAGS = 'doorkeeper.tags';
|
const KEY_TAGS = 'doorkeeper.tags';
|
||||||
|
|
||||||
|
const VIEW_FULL = 'full';
|
||||||
|
const VIEW_SHORT = 'short';
|
||||||
|
|
||||||
public function getPriority() {
|
public function getPriority() {
|
||||||
return 350.0;
|
return 350.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function addDoorkeeperTag(array $spec) {
|
protected function addDoorkeeperTag(array $spec) {
|
||||||
|
PhutilTypeSpec::checkMap(
|
||||||
|
$spec,
|
||||||
|
array(
|
||||||
|
'href' => 'string',
|
||||||
|
'tag' => 'map<string, wild>',
|
||||||
|
|
||||||
|
'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;
|
$key = self::KEY_TAGS;
|
||||||
$engine = $this->getEngine();
|
$engine = $this->getEngine();
|
||||||
$token = $engine->storeText(get_class($this));
|
$token = $engine->storeText(get_class($this));
|
||||||
|
@ -36,19 +66,26 @@ abstract class DoorkeeperRemarkupRule extends PhutilRemarkupRule {
|
||||||
|
|
||||||
$refs = array();
|
$refs = array();
|
||||||
foreach ($tags as $spec) {
|
foreach ($tags as $spec) {
|
||||||
|
$href = $spec['href'];
|
||||||
|
$name = idx($spec, 'name', $href);
|
||||||
|
|
||||||
|
$this->assertFlatText($href);
|
||||||
|
$this->assertFlatText($name);
|
||||||
|
|
||||||
|
if ($this->getEngine()->isTextMode()) {
|
||||||
|
$view = "{$name} <{$href}>";
|
||||||
|
} else {
|
||||||
$tag_id = celerity_generate_unique_node_id();
|
$tag_id = celerity_generate_unique_node_id();
|
||||||
|
|
||||||
$refs[] = array(
|
$refs[] = array(
|
||||||
'id' => $tag_id,
|
'id' => $tag_id,
|
||||||
|
'view' => $spec['view'],
|
||||||
) + $spec['tag'];
|
) + $spec['tag'];
|
||||||
|
|
||||||
if ($this->getEngine()->isTextMode()) {
|
|
||||||
$view = $spec['href'];
|
|
||||||
} else {
|
|
||||||
$view = id(new PHUITagView())
|
$view = id(new PHUITagView())
|
||||||
->setID($tag_id)
|
->setID($tag_id)
|
||||||
->setName($this->assertFlatText($spec['href']))
|
->setName($name)
|
||||||
->setHref($this->assertFlatText($spec['href']))
|
->setHref($href)
|
||||||
->setType(PHUITagView::TYPE_OBJECT)
|
->setType(PHUITagView::TYPE_OBJECT)
|
||||||
->setExternal(true);
|
->setExternal(true);
|
||||||
}
|
}
|
||||||
|
@ -56,7 +93,9 @@ abstract class DoorkeeperRemarkupRule extends PhutilRemarkupRule {
|
||||||
$engine->overwriteStoredText($spec['token'], $view);
|
$engine->overwriteStoredText($spec['token'], $view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($refs) {
|
||||||
Javelin::initBehavior('doorkeeper-tag', array('tags' => $refs));
|
Javelin::initBehavior('doorkeeper-tag', array('tags' => $refs));
|
||||||
|
}
|
||||||
|
|
||||||
$engine->setTextMetadata($key, array());
|
$engine->setTextMetadata($key, array());
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,9 +40,19 @@ JX.behavior('doorkeeper-tag', function(config, statics) {
|
||||||
};
|
};
|
||||||
|
|
||||||
for (var ii = 0; ii < tags.length; ii++) {
|
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) {
|
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 {
|
} else {
|
||||||
need.push(tags[ii]);
|
need.push(tags[ii]);
|
||||||
keys[tags[ii].id] = tag_key;
|
keys[tags[ii].id] = tag_key;
|
||||||
|
@ -54,7 +64,11 @@ JX.behavior('doorkeeper-tag', function(config, statics) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need.length) {
|
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); })
|
.setHandler(function(r) { draw(r.tags); })
|
||||||
.start();
|
.start();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue