mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-24 22:40:55 +01:00
Group inline transactions in Pholio
Summary: Fixes T2639 by grouping related transactions at display time, so all the inlines merge into a nice block. (Note that this does not do anything about T2709 yet, so there's still no way to figure out where the inlines actually are.) Test Plan: {F35262} Reviewers: chad Reviewed By: chad CC: aran Maniphest Tasks: T2639 Differential Revision: https://secure.phabricator.com/D5313
This commit is contained in:
parent
a858c14791
commit
eb010b2efc
10 changed files with 205 additions and 18 deletions
|
@ -1484,6 +1484,7 @@ phutil_register_library_map(array(
|
|||
'PholioTransactionComment' => 'applications/pholio/storage/PholioTransactionComment.php',
|
||||
'PholioTransactionQuery' => 'applications/pholio/query/PholioTransactionQuery.php',
|
||||
'PholioTransactionType' => 'applications/pholio/constants/PholioTransactionType.php',
|
||||
'PholioTransactionView' => 'applications/pholio/view/PholioTransactionView.php',
|
||||
'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php',
|
||||
'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/PhortuneStripeBaseController.php',
|
||||
'PhortuneStripePaymentFormView' => 'applications/phortune/stripe/view/PhortuneStripePaymentFormView.php',
|
||||
|
@ -2998,6 +2999,7 @@ phutil_register_library_map(array(
|
|||
'PholioTransactionComment' => 'PhabricatorApplicationTransactionComment',
|
||||
'PholioTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'PholioTransactionType' => 'PholioConstants',
|
||||
'PholioTransactionView' => 'PhabricatorApplicationTransactionView',
|
||||
'PhortuneMonthYearExpiryControl' => 'AphrontFormControl',
|
||||
'PhortuneStripeBaseController' => 'PhabricatorController',
|
||||
'PhortuneStripePaymentFormView' => 'AphrontView',
|
||||
|
|
|
@ -77,7 +77,7 @@ final class PholioMockViewController extends PholioController {
|
|||
->setMock($mock)
|
||||
->setImageID($this->imageID);
|
||||
|
||||
$xaction_view = id(new PhabricatorApplicationTransactionView())
|
||||
$xaction_view = id(new PholioTransactionView())
|
||||
->setUser($this->getRequest()->getUser())
|
||||
->setTransactions($xactions)
|
||||
->setMarkupEngine($engine);
|
||||
|
|
|
@ -17,6 +17,10 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
|
|||
return new PholioTransactionComment();
|
||||
}
|
||||
|
||||
public function getApplicationTransactionViewObject() {
|
||||
return new PholioTransactionView();
|
||||
}
|
||||
|
||||
public function getApplicationObjectTypeName() {
|
||||
return pht('mock');
|
||||
}
|
||||
|
@ -33,13 +37,22 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
|
|||
return parent::shouldHide();
|
||||
}
|
||||
|
||||
public function getIcon() {
|
||||
switch ($this->getTransactionType()) {
|
||||
case PholioTransactionType::TYPE_INLINE:
|
||||
return 'comment';
|
||||
}
|
||||
return parent::getIcon();
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
$author_phid = $this->getAuthorPHID();
|
||||
|
||||
$old = $this->getOldValue();
|
||||
$new = $this->getNewValue();
|
||||
|
||||
switch ($this->getTransactionType()) {
|
||||
$type = $this->getTransactionType();
|
||||
switch ($type) {
|
||||
case PholioTransactionType::TYPE_NAME:
|
||||
return pht(
|
||||
'%s renamed this mock from "%s" to "%s".',
|
||||
|
@ -53,9 +66,17 @@ final class PholioTransaction extends PhabricatorApplicationTransaction {
|
|||
$this->renderHandleLink($author_phid));
|
||||
break;
|
||||
case PholioTransactionType::TYPE_INLINE:
|
||||
$count = 1;
|
||||
foreach ($this->getTransactionGroup() as $xaction) {
|
||||
if ($xaction->getTransactionType() == $type) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
return pht(
|
||||
'%s added an inline comment.',
|
||||
$this->renderHandleLink($author_phid));
|
||||
'%s added %d inline comment(s).',
|
||||
$this->renderHandleLink($author_phid),
|
||||
$count);
|
||||
}
|
||||
|
||||
return parent::getTitle();
|
||||
|
|
83
src/applications/pholio/view/PholioTransactionView.php
Normal file
83
src/applications/pholio/view/PholioTransactionView.php
Normal file
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
final class PholioTransactionView
|
||||
extends PhabricatorApplicationTransactionView {
|
||||
|
||||
protected function shouldGroupTransactions(
|
||||
PhabricatorApplicationTransaction $u,
|
||||
PhabricatorApplicationTransaction $v) {
|
||||
|
||||
if ($u->getAuthorPHID() != $v->getAuthorPHID()) {
|
||||
// Don't group transactions by different authors.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (($v->getDateCreated() - $u->getDateCreated()) > 60) {
|
||||
// Don't group if transactions happend more than 60s apart.
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ($u->getTransactionType()) {
|
||||
case PhabricatorTransactions::TYPE_COMMENT:
|
||||
case PholioTransactionType::TYPE_INLINE:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ($v->getTransactionType()) {
|
||||
case PholioTransactionType::TYPE_INLINE:
|
||||
return true;
|
||||
}
|
||||
|
||||
return parent::shouldGroupTransactions($u, $v);
|
||||
}
|
||||
|
||||
protected function renderTransactionContent(
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
$out = array();
|
||||
|
||||
$group = $xaction->getTransactionGroup();
|
||||
if ($xaction->getTransactionType() == PholioTransactionType::TYPE_INLINE) {
|
||||
array_unshift($group, $xaction);
|
||||
} else {
|
||||
$out[] = parent::renderTransactionContent($xaction);
|
||||
}
|
||||
|
||||
if (!$group) {
|
||||
return $out;
|
||||
}
|
||||
|
||||
$inlines = array();
|
||||
foreach ($group as $xaction) {
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case PholioTransactionType::TYPE_INLINE:
|
||||
$inlines[] = $xaction;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown grouped transaction type!");
|
||||
}
|
||||
}
|
||||
|
||||
if ($inlines) {
|
||||
$header = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'phabricator-transaction-subheader',
|
||||
),
|
||||
pht('Inline Comments'));
|
||||
|
||||
$out[] = $header;
|
||||
foreach ($inlines as $inline) {
|
||||
if (!$inline->getComment()) {
|
||||
continue;
|
||||
}
|
||||
$out[] = parent::renderTransactionContent($inline);
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
}
|
|
@ -47,7 +47,14 @@ final class PhabricatorApplicationTransactionResponse
|
|||
}
|
||||
|
||||
public function reduceProxyResponse() {
|
||||
$view = id(new PhabricatorApplicationTransactionView())
|
||||
if ($this->getTransactions()) {
|
||||
$view = head($this->getTransactions())
|
||||
->getApplicationTransactionViewObject();
|
||||
} else {
|
||||
$view = new PhabricatorApplicationTransactionView();
|
||||
}
|
||||
|
||||
$view
|
||||
->setUser($this->getViewer())
|
||||
->setTransactions($this->getTransactions())
|
||||
->setIsPreview($this->isPreview);
|
||||
|
@ -70,4 +77,5 @@ final class PhabricatorApplicationTransactionResponse
|
|||
return $this->getProxy()->setContent($content);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -26,11 +26,16 @@ abstract class PhabricatorApplicationTransaction
|
|||
|
||||
private $handles;
|
||||
private $renderingTarget = self::TARGET_HTML;
|
||||
private $transactionGroup = array();
|
||||
|
||||
abstract public function getApplicationTransactionType();
|
||||
abstract public function getApplicationTransactionCommentObject();
|
||||
abstract public function getApplicationObjectTypeName();
|
||||
|
||||
public function getApplicationTransactionViewObject() {
|
||||
return new PhabricatorApplicationTransactionView();
|
||||
}
|
||||
|
||||
public function generatePHID() {
|
||||
$type = PhabricatorPHIDConstants::PHID_TYPE_XACT;
|
||||
$subtype = $this->getApplicationTransactionType();
|
||||
|
@ -329,6 +334,17 @@ abstract class PhabricatorApplicationTransaction
|
|||
return null;
|
||||
}
|
||||
|
||||
public function attachTransactionGroup(array $group) {
|
||||
assert_instances_of($group, 'PhabricatorApplicationTransaction');
|
||||
$this->transactionGroup = $group;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTransactionGroup() {
|
||||
return $this->transactionGroup;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
|
||||
|
||||
|
||||
|
|
|
@ -42,17 +42,33 @@ class PhabricatorApplicationTransactionView extends AphrontView {
|
|||
}
|
||||
|
||||
public function buildEvents() {
|
||||
$field = PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT;
|
||||
$engine = $this->getOrBuildEngine();
|
||||
|
||||
$user = $this->getUser();
|
||||
|
||||
$anchor = $this->anchorOffset;
|
||||
$events = array();
|
||||
foreach ($this->transactions as $xaction) {
|
||||
|
||||
$xactions = $this->transactions;
|
||||
foreach ($xactions as $key => $xaction) {
|
||||
if ($xaction->shouldHide()) {
|
||||
continue;
|
||||
unset($xactions[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$last = null;
|
||||
$last_key = null;
|
||||
$groups = array();
|
||||
foreach ($xactions as $key => $xaction) {
|
||||
if ($last && $this->shouldGroupTransactions($last, $xaction)) {
|
||||
$groups[$last_key][] = $xaction;
|
||||
unset($xactions[$key]);
|
||||
} else {
|
||||
$last = $xaction;
|
||||
$last_key = $key;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($xactions as $key => $xaction) {
|
||||
$xaction->attachTransactionGroup(idx($groups, $key, array()));
|
||||
|
||||
$event = id(new PhabricatorTimelineEventView())
|
||||
->setUser($user)
|
||||
|
@ -103,12 +119,9 @@ class PhabricatorApplicationTransactionView extends AphrontView {
|
|||
}
|
||||
}
|
||||
|
||||
if ($xaction->hasComment()) {
|
||||
$event->appendChild(
|
||||
$engine->getOutput($xaction->getComment(), $field));
|
||||
} else if ($has_deleted_comment) {
|
||||
$event->appendChild(phutil_tag('em', array(), pht(
|
||||
'This comment has been deleted.')));
|
||||
$content = $this->renderTransactionContent($xaction);
|
||||
if ($content) {
|
||||
$event->appendChild($content);
|
||||
}
|
||||
|
||||
$events[] = $event;
|
||||
|
@ -141,7 +154,7 @@ class PhabricatorApplicationTransactionView extends AphrontView {
|
|||
}
|
||||
|
||||
|
||||
private function getOrBuildEngine() {
|
||||
protected function getOrBuildEngine() {
|
||||
if ($this->engine) {
|
||||
return $this->engine;
|
||||
}
|
||||
|
@ -215,6 +228,32 @@ class PhabricatorApplicationTransactionView extends AphrontView {
|
|||
);
|
||||
}
|
||||
|
||||
protected function shouldGroupTransactions(
|
||||
PhabricatorApplicationTransaction $u,
|
||||
PhabricatorApplicationTransaction $v) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function renderTransactionContent(
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
$field = PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT;
|
||||
$engine = $this->getOrBuildEngine();
|
||||
$comment = $xaction->getComment();
|
||||
|
||||
if ($comment) {
|
||||
if ($comment->getIsDeleted()) {
|
||||
return phutil_tag(
|
||||
'em',
|
||||
array(),
|
||||
pht('This comment has been deleted.'));
|
||||
} else {
|
||||
return $engine->getOutput($comment, $field);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -279,6 +279,13 @@ abstract class PhabricatorBaseEnglishTranslation
|
|||
'You have %d unresolved setup issues...',
|
||||
),
|
||||
|
||||
'%s added %d inline comment(s).' => array(
|
||||
array(
|
||||
'%s added an inline comment.',
|
||||
'%s added inline comments.',
|
||||
),
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ final class PhabricatorPropertyListView extends AphrontView {
|
|||
array(
|
||||
'class' => 'phabricator-property-list-properties',
|
||||
),
|
||||
$this->renderSingleView($items));
|
||||
$items);
|
||||
|
||||
$shortcuts = null;
|
||||
if ($this->hasKeyboardShortcuts) {
|
||||
|
|
|
@ -51,3 +51,14 @@
|
|||
padding: .3em 1em;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.phabricator-transaction-subheader {
|
||||
color: #888888;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
padding-bottom: 4px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
div.phabricator-remarkup + .phabricator-transaction-subheader {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue