mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-10 23:01:04 +01:00
Add an "Add CCs" action to Differential
Summary: We currently have only an "Add reviewers" action, add "Add CCs". This can also be accomplished less-discoverably with mentions. Test Plan: Added reviewers and CCs to revisions. Toggled display between reviewers and CCs. Reviewed By: jungejason Reviewers: tomo, mroch, jsp, jungejason, aran, tuomaspelkonen CC: aran, jungejason Differential Revision: 521
This commit is contained in:
parent
4469ef8f30
commit
bb4cf7d6b3
10 changed files with 147 additions and 49 deletions
|
@ -381,9 +381,9 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/js/application/differential/behavior-accept-with-errors.js',
|
'disk' => '/rsrc/js/application/differential/behavior-accept-with-errors.js',
|
||||||
),
|
),
|
||||||
'javelin-behavior-differential-add-reviewers' =>
|
'javelin-behavior-differential-add-reviewers-and-ccs' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/dc79790c/rsrc/js/application/differential/behavior-add-reviewers.js',
|
'uri' => '/res/fc352745/rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -393,7 +393,7 @@ celerity_register_resource_map(array(
|
||||||
3 => 'javelin-typeahead',
|
3 => 'javelin-typeahead',
|
||||||
4 => 'javelin-typeahead-preloaded-source',
|
4 => 'javelin-typeahead-preloaded-source',
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/js/application/differential/behavior-add-reviewers.js',
|
'disk' => '/rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js',
|
||||||
),
|
),
|
||||||
'javelin-behavior-differential-comment-jump' =>
|
'javelin-behavior-differential-comment-jump' =>
|
||||||
array(
|
array(
|
||||||
|
@ -893,7 +893,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'maniphest-task-summary-css' =>
|
'maniphest-task-summary-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/e86389c4/rsrc/css/application/maniphest/task-summary.css',
|
'uri' => '/res/14cb4b5d/rsrc/css/application/maniphest/task-summary.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
|
|
@ -32,6 +32,7 @@ final class DifferentialAction {
|
||||||
const ACTION_TESTPLAN = 'testplan';
|
const ACTION_TESTPLAN = 'testplan';
|
||||||
const ACTION_CREATE = 'create';
|
const ACTION_CREATE = 'create';
|
||||||
const ACTION_ADDREVIEWERS = 'add_reviewers';
|
const ACTION_ADDREVIEWERS = 'add_reviewers';
|
||||||
|
const ACTION_ADDCCS = 'add_ccs';
|
||||||
|
|
||||||
public static function getActionPastTenseVerb($action) {
|
public static function getActionPastTenseVerb($action) {
|
||||||
static $verbs = array(
|
static $verbs = array(
|
||||||
|
@ -49,6 +50,7 @@ final class DifferentialAction {
|
||||||
self::ACTION_TESTPLAN => 'explained the test plan for',
|
self::ACTION_TESTPLAN => 'explained the test plan for',
|
||||||
self::ACTION_CREATE => 'created',
|
self::ACTION_CREATE => 'created',
|
||||||
self::ACTION_ADDREVIEWERS => 'added reviewers to',
|
self::ACTION_ADDREVIEWERS => 'added reviewers to',
|
||||||
|
self::ACTION_ADDCCS => 'added CCs to',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!empty($verbs[$action])) {
|
if (!empty($verbs[$action])) {
|
||||||
|
@ -69,6 +71,7 @@ final class DifferentialAction {
|
||||||
self::ACTION_RECLAIM => 'Reclaim Revision',
|
self::ACTION_RECLAIM => 'Reclaim Revision',
|
||||||
self::ACTION_RESIGN => 'Resign as Reviewer',
|
self::ACTION_RESIGN => 'Resign as Reviewer',
|
||||||
self::ACTION_ADDREVIEWERS => 'Add Reviewers',
|
self::ACTION_ADDREVIEWERS => 'Add Reviewers',
|
||||||
|
self::ACTION_ADDCCS => 'Add CCs',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!empty($verbs[$action])) {
|
if (!empty($verbs[$action])) {
|
||||||
|
|
|
@ -33,6 +33,7 @@ class DifferentialCommentSaveController extends DifferentialController {
|
||||||
$comment = $request->getStr('comment');
|
$comment = $request->getStr('comment');
|
||||||
$action = $request->getStr('action');
|
$action = $request->getStr('action');
|
||||||
$reviewers = $request->getArr('reviewers');
|
$reviewers = $request->getArr('reviewers');
|
||||||
|
$ccs = $request->getArr('ccs');
|
||||||
|
|
||||||
$editor = new DifferentialCommentEditor(
|
$editor = new DifferentialCommentEditor(
|
||||||
$revision,
|
$revision,
|
||||||
|
@ -44,6 +45,7 @@ class DifferentialCommentSaveController extends DifferentialController {
|
||||||
->setAttachInlineComments(true)
|
->setAttachInlineComments(true)
|
||||||
->setAddCC($action != DifferentialAction::ACTION_RESIGN)
|
->setAddCC($action != DifferentialAction::ACTION_RESIGN)
|
||||||
->setAddedReviewers($reviewers)
|
->setAddedReviewers($reviewers)
|
||||||
|
->setAddedCCs($ccs)
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
// TODO: Diff change detection?
|
// TODO: Diff change detection?
|
||||||
|
|
|
@ -89,6 +89,14 @@ class DifferentialRevisionViewController extends DifferentialController {
|
||||||
$object_phids[] = $phid;
|
$object_phids[] = $phid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$added_ccs = idx(
|
||||||
|
$metadata,
|
||||||
|
DifferentialComment::METADATA_ADDED_CCS);
|
||||||
|
if ($added_ccs) {
|
||||||
|
foreach ($added_ccs as $phid) {
|
||||||
|
$object_phids[] = $phid;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($revision->getAttached() as $type => $phids) {
|
foreach ($revision->getAttached() as $type => $phids) {
|
||||||
|
@ -570,6 +578,7 @@ class DifferentialRevisionViewController extends DifferentialController {
|
||||||
}
|
}
|
||||||
|
|
||||||
$actions[DifferentialAction::ACTION_ADDREVIEWERS] = true;
|
$actions[DifferentialAction::ACTION_ADDREVIEWERS] = true;
|
||||||
|
$actions[DifferentialAction::ACTION_ADDCCS] = true;
|
||||||
|
|
||||||
return array_keys(array_filter($actions));
|
return array_keys(array_filter($actions));
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ class DifferentialCommentEditor {
|
||||||
protected $addCC;
|
protected $addCC;
|
||||||
protected $changedByCommit;
|
protected $changedByCommit;
|
||||||
protected $addedReviewers = array();
|
protected $addedReviewers = array();
|
||||||
|
private $addedCCs = array();
|
||||||
|
|
||||||
private $parentMessageID;
|
private $parentMessageID;
|
||||||
|
|
||||||
|
@ -78,6 +79,15 @@ class DifferentialCommentEditor {
|
||||||
return $this->addedReviewers;
|
return $this->addedReviewers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setAddedCCs($added_ccs) {
|
||||||
|
$this->addedCCs = $added_ccs;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAddedCCs() {
|
||||||
|
return $this->addedCCs;
|
||||||
|
}
|
||||||
|
|
||||||
public function save() {
|
public function save() {
|
||||||
$revision = $this->revision;
|
$revision = $this->revision;
|
||||||
$action = $this->action;
|
$action = $this->action;
|
||||||
|
@ -258,7 +268,34 @@ class DifferentialCommentEditor {
|
||||||
$action = DifferentialAction::ACTION_COMMENT;
|
$action = DifferentialAction::ACTION_COMMENT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DifferentialAction::ACTION_ADDCCS:
|
||||||
|
$added_ccs = $this->getAddedCCs();
|
||||||
|
|
||||||
|
$current_ccs = $revision->getCCPHIDs();
|
||||||
|
if ($current_ccs) {
|
||||||
|
$current_ccs = array_combine($current_ccs, $current_ccs);
|
||||||
|
foreach ($added_ccs as $k => $cc) {
|
||||||
|
if (isset($current_ccs[$cc])) {
|
||||||
|
unset($added_ccs[$k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($added_ccs) {
|
||||||
|
foreach ($added_ccs as $cc) {
|
||||||
|
DifferentialRevisionEditor::addCC(
|
||||||
|
$revision,
|
||||||
|
$cc,
|
||||||
|
$this->actorPHID);
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = DifferentialComment::METADATA_ADDED_CCS;
|
||||||
|
$metadata[$key] = $added_ccs;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$action = DifferentialAction::ACTION_COMMENT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception('Unsupported action.');
|
throw new Exception('Unsupported action.');
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
|
|
||||||
class DifferentialComment extends DifferentialDAO {
|
class DifferentialComment extends DifferentialDAO {
|
||||||
|
|
||||||
const METADATA_ADDED_REVIEWERS = 'added-reviewers';
|
const METADATA_ADDED_REVIEWERS = 'added-reviewers';
|
||||||
|
const METADATA_ADDED_CCS = 'added-ccs';
|
||||||
|
|
||||||
protected $authorPHID;
|
protected $authorPHID;
|
||||||
protected $revisionID;
|
protected $revisionID;
|
||||||
|
|
|
@ -93,6 +93,14 @@ final class DifferentialAddCommentView extends AphrontView {
|
||||||
->setControlStyle('display: none')
|
->setControlStyle('display: none')
|
||||||
->setID('add-reviewers-tokenizer')
|
->setID('add-reviewers-tokenizer')
|
||||||
->setDisableBehavior(true))
|
->setDisableBehavior(true))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormTokenizerControl())
|
||||||
|
->setLabel('Add CCs')
|
||||||
|
->setName('ccs')
|
||||||
|
->setControlID('add-ccs')
|
||||||
|
->setControlStyle('display: none')
|
||||||
|
->setID('add-ccs-tokenizer')
|
||||||
|
->setDisableBehavior(true))
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormTextAreaControl())
|
id(new AphrontFormTextAreaControl())
|
||||||
->setName('comment')
|
->setName('comment')
|
||||||
|
@ -104,12 +112,21 @@ final class DifferentialAddCommentView extends AphrontView {
|
||||||
->setValue('Clowncopterize'));
|
->setValue('Clowncopterize'));
|
||||||
|
|
||||||
Javelin::initBehavior(
|
Javelin::initBehavior(
|
||||||
'differential-add-reviewers',
|
'differential-add-reviewers-and-ccs',
|
||||||
array(
|
array(
|
||||||
'src' => '/typeahead/common/users/',
|
'dynamic' => array(
|
||||||
'tokenizer' => 'add-reviewers-tokenizer',
|
'add_reviewers' => array(
|
||||||
|
'tokenizer' => 'add-reviewers-tokenizer',
|
||||||
|
'src' => '/typeahead/common/users/',
|
||||||
|
'row' => 'add-reviewers',
|
||||||
|
),
|
||||||
|
'add_ccs' => array(
|
||||||
|
'tokenizer' => 'add-ccs-tokenizer',
|
||||||
|
'src' => '/typeahead/common/mailable/',
|
||||||
|
'row' => 'add-ccs',
|
||||||
|
),
|
||||||
|
),
|
||||||
'select' => 'comment-action',
|
'select' => 'comment-action',
|
||||||
'row' => 'add-reviewers',
|
|
||||||
));
|
));
|
||||||
|
|
||||||
$diff = $revision->loadActiveDiff();
|
$diff = $revision->loadActiveDiff();
|
||||||
|
|
|
@ -231,14 +231,19 @@ final class DifferentialRevisionCommentView extends AphrontView {
|
||||||
$metadata,
|
$metadata,
|
||||||
DifferentialComment::METADATA_ADDED_REVIEWERS);
|
DifferentialComment::METADATA_ADDED_REVIEWERS);
|
||||||
if ($added_reviewers) {
|
if ($added_reviewers) {
|
||||||
$reviewers = array();
|
$reviewers = 'Added reviewers: '.$this->renderHandleList(
|
||||||
foreach ($added_reviewers as $phid) {
|
$added_reviewers);
|
||||||
$reviewers[] = $this->handles[$phid]->renderLink();
|
|
||||||
}
|
|
||||||
$reviewers = 'Added reviewers: '.implode(', ', $reviewers);
|
|
||||||
$metadata_blocks[] = $reviewers;
|
$metadata_blocks[] = $reviewers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$added_ccs = idx(
|
||||||
|
$metadata,
|
||||||
|
DifferentialComment::METADATA_ADDED_CCS);
|
||||||
|
if ($added_ccs) {
|
||||||
|
$ccs = 'Added CCs: '.$this->renderHandleList($added_ccs);
|
||||||
|
$metadata_blocks[] = $ccs;
|
||||||
|
}
|
||||||
|
|
||||||
if ($metadata_blocks) {
|
if ($metadata_blocks) {
|
||||||
$metadata_blocks =
|
$metadata_blocks =
|
||||||
'<div class="differential-comment-metadata">'.
|
'<div class="differential-comment-metadata">'.
|
||||||
|
@ -271,4 +276,12 @@ final class DifferentialRevisionCommentView extends AphrontView {
|
||||||
'</div>');
|
'</div>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function renderHandleList(array $phids) {
|
||||||
|
$result = array();
|
||||||
|
foreach ($phids as $phid) {
|
||||||
|
$result[] = $this->handles[$phid]->renderLink();
|
||||||
|
}
|
||||||
|
return implode(', ', $result);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
* @provides javelin-behavior-differential-add-reviewers-and-ccs
|
||||||
|
* @requires javelin-behavior
|
||||||
|
* javelin-dom
|
||||||
|
* javelin-tokenizer
|
||||||
|
* javelin-typeahead
|
||||||
|
* javelin-typeahead-preloaded-source
|
||||||
|
*/
|
||||||
|
|
||||||
|
JX.behavior('differential-add-reviewers-and-ccs', function(config) {
|
||||||
|
|
||||||
|
function buildTokenizer(props) {
|
||||||
|
var root = JX.$(props.tokenizer);
|
||||||
|
var datasource = new JX.TypeaheadPreloadedSource(props.src);
|
||||||
|
|
||||||
|
var typeahead = new JX.Typeahead(root);
|
||||||
|
typeahead.setDatasource(datasource);
|
||||||
|
|
||||||
|
var tokenizer = new JX.Tokenizer(root);
|
||||||
|
tokenizer.setTypeahead(typeahead);
|
||||||
|
tokenizer.start();
|
||||||
|
|
||||||
|
return tokenizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dynamic = {};
|
||||||
|
for (var k in config.dynamic) {
|
||||||
|
props = config.dynamic[k];
|
||||||
|
dynamic[k] = {
|
||||||
|
row : JX.$(props.row),
|
||||||
|
tokenizer : buildTokenizer(props)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
JX.DOM.listen(
|
||||||
|
JX.$(config.select),
|
||||||
|
'change',
|
||||||
|
null,
|
||||||
|
function(e) {
|
||||||
|
var v = JX.$(config.select).value;
|
||||||
|
for (var k in dynamic) {
|
||||||
|
if (v == k) {
|
||||||
|
JX.DOM.show(dynamic[k].row);
|
||||||
|
dynamic[k].tokenizer.refresh();
|
||||||
|
} else {
|
||||||
|
JX.DOM.hide(dynamic[k].row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
/**
|
|
||||||
* @provides javelin-behavior-differential-add-reviewers
|
|
||||||
* @requires javelin-behavior
|
|
||||||
* javelin-dom
|
|
||||||
* javelin-tokenizer
|
|
||||||
* javelin-typeahead
|
|
||||||
* javelin-typeahead-preloaded-source
|
|
||||||
*/
|
|
||||||
|
|
||||||
JX.behavior('differential-add-reviewers', function(config) {
|
|
||||||
|
|
||||||
var root = JX.$(config.tokenizer);
|
|
||||||
var datasource = new JX.TypeaheadPreloadedSource(config.src);
|
|
||||||
|
|
||||||
var typeahead = new JX.Typeahead(root);
|
|
||||||
typeahead.setDatasource(datasource);
|
|
||||||
|
|
||||||
var tokenizer = new JX.Tokenizer(root);
|
|
||||||
tokenizer.setTypeahead(typeahead);
|
|
||||||
tokenizer.start();
|
|
||||||
|
|
||||||
JX.DOM.listen(
|
|
||||||
JX.$(config.select),
|
|
||||||
'change',
|
|
||||||
null,
|
|
||||||
function(e) {
|
|
||||||
if (JX.$(config.select).value == 'add_reviewers') {
|
|
||||||
JX.DOM.show(JX.$(config.row));
|
|
||||||
tokenizer.refresh();
|
|
||||||
} else {
|
|
||||||
JX.DOM.hide(JX.$(config.row));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
Loading…
Reference in a new issue