mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-24 06:20:56 +01:00
Convert DifferentialRevision view to new PHUIDiffTableOfContentsListView
Summary: Ref T2183. Introduces a new View which can (in theory) unify the Revision, Diff and Commit table of contents views. This has the same behavior as before, but accepts slightly more general primitives and parameters and has somewhat cleaner code. I've made one intentinoal behavior change: removing the "Open All in Editor" button. I suspect this is essentially unused, and is a pain to keep around. We can look at restoring it if anyone notices. Test Plan: Looked at a bunch of revisions, no changes from before. Reviewers: chad Reviewed By: chad Maniphest Tasks: T2183 Differential Revision: https://secure.phabricator.com/D13908
This commit is contained in:
parent
fca716d699
commit
cb912d1735
4 changed files with 412 additions and 10 deletions
|
@ -1362,6 +1362,8 @@ phutil_register_library_map(array(
|
|||
'PHUIDiffInlineCommentView' => 'infrastructure/diff/view/PHUIDiffInlineCommentView.php',
|
||||
'PHUIDiffOneUpInlineCommentRowScaffold' => 'infrastructure/diff/view/PHUIDiffOneUpInlineCommentRowScaffold.php',
|
||||
'PHUIDiffRevealIconView' => 'infrastructure/diff/view/PHUIDiffRevealIconView.php',
|
||||
'PHUIDiffTableOfContentsItemView' => 'infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php',
|
||||
'PHUIDiffTableOfContentsListView' => 'infrastructure/diff/view/PHUIDiffTableOfContentsListView.php',
|
||||
'PHUIDiffTwoUpInlineCommentRowScaffold' => 'infrastructure/diff/view/PHUIDiffTwoUpInlineCommentRowScaffold.php',
|
||||
'PHUIDocumentExample' => 'applications/uiexample/examples/PHUIDocumentExample.php',
|
||||
'PHUIDocumentView' => 'view/phui/PHUIDocumentView.php',
|
||||
|
@ -5157,6 +5159,8 @@ phutil_register_library_map(array(
|
|||
'PHUIDiffInlineCommentView' => 'AphrontView',
|
||||
'PHUIDiffOneUpInlineCommentRowScaffold' => 'PHUIDiffInlineCommentRowScaffold',
|
||||
'PHUIDiffRevealIconView' => 'AphrontView',
|
||||
'PHUIDiffTableOfContentsItemView' => 'AphrontView',
|
||||
'PHUIDiffTableOfContentsListView' => 'AphrontView',
|
||||
'PHUIDiffTwoUpInlineCommentRowScaffold' => 'PHUIDiffInlineCommentRowScaffold',
|
||||
'PHUIDocumentExample' => 'PhabricatorUIExample',
|
||||
'PHUIDocumentView' => 'AphrontTagView',
|
||||
|
|
|
@ -349,16 +349,10 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
|||
$other_view = $this->renderOtherRevisions($other_revisions);
|
||||
}
|
||||
|
||||
$toc_view = new DifferentialDiffTableOfContentsView();
|
||||
$toc_view->setChangesets($changesets);
|
||||
$toc_view->setVisibleChangesets($visible_changesets);
|
||||
$toc_view->setRenderingReferences($rendering_references);
|
||||
$toc_view->setCoverageMap($target->loadCoverageMap($user));
|
||||
if ($repository) {
|
||||
$toc_view->setRepository($repository);
|
||||
}
|
||||
$toc_view->setDiff($target);
|
||||
$toc_view->setUser($user);
|
||||
$toc_view = $this->buildTableOfContents(
|
||||
$changesets,
|
||||
$visible_changesets,
|
||||
$target->loadCoverageMap($user));
|
||||
|
||||
$comment_form = null;
|
||||
if (!$viewer_is_anonymous) {
|
||||
|
@ -1042,5 +1036,34 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
|||
return $view;
|
||||
}
|
||||
|
||||
private function buildTableOfContents(
|
||||
array $changesets,
|
||||
array $visible_changesets,
|
||||
array $coverage) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$toc_view = id(new PHUIDiffTableOfContentsListView())
|
||||
->setUser($viewer);
|
||||
|
||||
foreach ($changesets as $changeset_id => $changeset) {
|
||||
$is_visible = isset($visible_changesets[$changeset_id]);
|
||||
$anchor = $changeset->getAnchorName();
|
||||
|
||||
$filename = $changeset->getFilename();
|
||||
$coverage_id = 'differential-mcoverage-'.md5($filename);
|
||||
|
||||
$item = id(new PHUIDiffTableOfContentsItemView())
|
||||
->setChangeset($changeset)
|
||||
->setIsVisible($is_visible)
|
||||
->setAnchor($anchor)
|
||||
->setCoverage(idx($coverage, $filename))
|
||||
->setCoverageID($coverage_id);
|
||||
|
||||
$toc_view->addItem($item);
|
||||
}
|
||||
|
||||
return $toc_view;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
295
src/infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php
Normal file
295
src/infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php
Normal file
|
@ -0,0 +1,295 @@
|
|||
<?php
|
||||
|
||||
final class PHUIDiffTableOfContentsItemView extends AphrontView {
|
||||
|
||||
private $changeset;
|
||||
private $isVisible;
|
||||
private $anchor;
|
||||
private $coverage;
|
||||
private $coverageID;
|
||||
|
||||
public function setChangeset(DifferentialChangeset $changeset) {
|
||||
$this->changeset = $changeset;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getChangeset() {
|
||||
return $this->changeset;
|
||||
}
|
||||
|
||||
public function setIsVisible($is_visible) {
|
||||
$this->isVisible = $is_visible;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsVisible() {
|
||||
return $this->isVisible;
|
||||
}
|
||||
|
||||
public function setAnchor($anchor) {
|
||||
$this->anchor = $anchor;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAnchor() {
|
||||
return $this->anchor;
|
||||
}
|
||||
|
||||
public function setCoverage($coverage) {
|
||||
$this->coverage = $coverage;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCoverage() {
|
||||
return $this->coverage;
|
||||
}
|
||||
|
||||
public function setCoverageID($coverage_id) {
|
||||
$this->coverageID = $coverage_id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCoverageID() {
|
||||
return $this->coverageID;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$changeset = $this->getChangeset();
|
||||
|
||||
$cells = array();
|
||||
|
||||
$cells[] = $this->renderPathChangeCharacter();
|
||||
$cells[] = $this->renderPropertyChangeCharacter();
|
||||
$cells[] = $this->renderPropertyChangeDescription();
|
||||
|
||||
$link = $this->renderChangesetLink();
|
||||
$lines = $this->renderChangesetLines();
|
||||
$meta = $this->renderChangesetMetadata();
|
||||
|
||||
$cells[] = array(
|
||||
$link,
|
||||
$lines,
|
||||
$meta,
|
||||
);
|
||||
|
||||
$cells[] = $this->renderCoverage();
|
||||
$cells[] = $this->renderModifiedCoverage();
|
||||
|
||||
return $cells;
|
||||
}
|
||||
|
||||
private function renderPathChangeCharacter() {
|
||||
$changeset = $this->getChangeset();
|
||||
$type = $changeset->getChangeType();
|
||||
|
||||
$color = DifferentialChangeType::getSummaryColorForChangeType($type);
|
||||
$char = DifferentialChangeType::getSummaryCharacterForChangeType($type);
|
||||
$title = DifferentialChangeType::getFullNameForChangeType($type);
|
||||
|
||||
return javelin_tag(
|
||||
'span',
|
||||
array(
|
||||
'sigil' => 'has-tip',
|
||||
'meta' => array(
|
||||
'tip' => $title,
|
||||
'align' => 'E',
|
||||
),
|
||||
'class' => 'phui-text-'.$color,
|
||||
),
|
||||
$char);
|
||||
}
|
||||
|
||||
private function renderPropertyChangeCharacter() {
|
||||
$changeset = $this->getChangeset();
|
||||
|
||||
$old = $changeset->getOldProperties();
|
||||
$new = $changeset->getNewProperties();
|
||||
|
||||
if ($old === $new) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return javelin_tag(
|
||||
'span',
|
||||
array(
|
||||
'sigil' => 'has-tip',
|
||||
'meta' => array(
|
||||
'tip' => pht('Properties Modified'),
|
||||
'align' => 'E',
|
||||
),
|
||||
),
|
||||
'M');
|
||||
}
|
||||
|
||||
private function renderPropertyChangeDescription() {
|
||||
$changeset = $this->getChangeset();
|
||||
|
||||
$file_type = $changeset->getFileType();
|
||||
|
||||
$desc = DifferentialChangeType::getShortNameForFileType($file_type);
|
||||
if ($desc === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return pht('(%s)', $desc);
|
||||
}
|
||||
|
||||
private function renderChangesetLink() {
|
||||
$anchor = $this->getAnchor();
|
||||
|
||||
$changeset = $this->getChangeset();
|
||||
$name = $changeset->getDisplayFilename();
|
||||
|
||||
$change_type = $changeset->getChangeType();
|
||||
if (DifferentialChangeType::isOldLocationChangeType($change_type)) {
|
||||
$away = $changeset->getAwayPaths();
|
||||
if (count($away) == 1) {
|
||||
if ($change_type == DifferentialChangeType::TYPE_MOVE_AWAY) {
|
||||
$right_arrow = "\xE2\x86\x92";
|
||||
$name = $this->renderRename($name, head($away), $right_arrow);
|
||||
}
|
||||
}
|
||||
} else if ($change_type == DifferentialChangeType::TYPE_MOVE_HERE) {
|
||||
$left_arrow = "\xE2\x86\x90";
|
||||
$name = $this->renderRename($name, $changeset->getOldFile(), $left_arrow);
|
||||
}
|
||||
|
||||
return javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '#'.$anchor,
|
||||
'sigil' => 'differential-load',
|
||||
'meta' => array(
|
||||
'id' => 'diff-'.$anchor,
|
||||
),
|
||||
),
|
||||
$name);
|
||||
}
|
||||
|
||||
private function renderChangesetLines() {
|
||||
$changeset = $this->getChangeset();
|
||||
|
||||
$line_count = $changeset->getAffectedLineCount();
|
||||
if (!$line_count) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ' '.pht('(%d line(s))', $line_count);
|
||||
}
|
||||
|
||||
private function renderCoverage() {
|
||||
$not_applicable = '-';
|
||||
|
||||
$coverage = $this->getCoverage();
|
||||
if (!strlen($coverage)) {
|
||||
return $not_applicable;
|
||||
}
|
||||
|
||||
$covered = substr_count($coverage, 'C');
|
||||
$not_covered = substr_count($coverage, 'U');
|
||||
|
||||
if (!$not_covered && !$covered) {
|
||||
return $not_applicable;
|
||||
}
|
||||
|
||||
return sprintf('%d%%', 100 * ($covered / ($covered + $not_covered)));
|
||||
}
|
||||
|
||||
private function renderModifiedCoverage() {
|
||||
$not_applicable = '-';
|
||||
|
||||
$coverage = $this->getCoverage();
|
||||
if (!strlen($coverage)) {
|
||||
return $not_applicable;
|
||||
}
|
||||
|
||||
if ($this->getIsVisible()) {
|
||||
$label = pht('Loading...');
|
||||
} else {
|
||||
$label = pht('?');
|
||||
}
|
||||
|
||||
return phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'id' => $this->getCoverageID(),
|
||||
'class' => 'differential-mcoverage-loading',
|
||||
),
|
||||
$label);
|
||||
}
|
||||
|
||||
private function renderChangesetMetadata() {
|
||||
$changeset = $this->getChangeset();
|
||||
$type = $changeset->getChangeType();
|
||||
|
||||
$meta = array();
|
||||
if (DifferentialChangeType::isOldLocationChangeType($type)) {
|
||||
$away = $changeset->getAwayPaths();
|
||||
if (count($away) > 1) {
|
||||
if ($type == DifferentialChangeType::TYPE_MULTICOPY) {
|
||||
$meta[] = pht('Deleted after being copied to multiple locations:');
|
||||
} else {
|
||||
$meta[] = pht('Copied to multiple locations:');
|
||||
}
|
||||
foreach ($away as $path) {
|
||||
$meta[] = $path;
|
||||
}
|
||||
} else {
|
||||
if ($type == DifferentialChangeType::TYPE_MOVE_AWAY) {
|
||||
// This case is handled when we render the path.
|
||||
} else {
|
||||
$meta[] = pht('Copied to %s', head($away));
|
||||
}
|
||||
}
|
||||
} else if ($type == DifferentialChangeType::TYPE_COPY_HERE) {
|
||||
$meta = pht('Copied from %s', $changeset->getOldFile());
|
||||
}
|
||||
|
||||
if (!$meta) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$meta = phutil_implode_html(phutil_tag('br'), $meta);
|
||||
|
||||
return phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'differential-toc-meta',
|
||||
),
|
||||
$meta);
|
||||
}
|
||||
|
||||
private function renderRename($self, $other, $arrow) {
|
||||
$old = explode('/', $self);
|
||||
$new = explode('/', $other);
|
||||
|
||||
$start = count($old);
|
||||
foreach ($old as $index => $part) {
|
||||
if (!isset($new[$index]) || $part != $new[$index]) {
|
||||
$start = $index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$end = count($old);
|
||||
foreach (array_reverse($old) as $from_end => $part) {
|
||||
$index = count($new) - $from_end - 1;
|
||||
if (!isset($new[$index]) || $part != $new[$index]) {
|
||||
$end = $from_end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$rename =
|
||||
'{'.
|
||||
implode('/', array_slice($old, $start, count($old) - $end - $start)).
|
||||
' '.$arrow.' '.
|
||||
implode('/', array_slice($new, $start, count($new) - $end - $start)).
|
||||
'}';
|
||||
|
||||
array_splice($new, $start, count($new) - $end - $start, $rename);
|
||||
|
||||
return implode('/', $new);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
final class PHUIDiffTableOfContentsListView extends AphrontView {
|
||||
|
||||
private $items = array();
|
||||
|
||||
public function addItem(PHUIDiffTableOfContentsItemView $item) {
|
||||
$this->items[] = $item;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$this->requireResource('differential-core-view-css');
|
||||
$this->requireResource('differential-table-of-contents-css');
|
||||
$this->requireResource('phui-text-css');
|
||||
|
||||
$items = $this->items;
|
||||
|
||||
$rows = array();
|
||||
foreach ($items as $item) {
|
||||
$rows[] = $item->render();
|
||||
}
|
||||
|
||||
$reveal_link = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'sigil' => 'differential-reveal-all',
|
||||
'mustcapture' => true,
|
||||
'class' => 'button differential-toc-reveal-all',
|
||||
),
|
||||
pht('Show All Context'));
|
||||
|
||||
$buttons = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'differential-toc-buttons grouped',
|
||||
),
|
||||
$reveal_link);
|
||||
|
||||
$table = id(new AphrontTableView($rows))
|
||||
->setHeaders(
|
||||
array(
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
pht('Path'),
|
||||
pht('Coverage (All)'),
|
||||
pht('Coverage (Touched)'),
|
||||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
'differential-toc-char center',
|
||||
'differential-toc-prop center',
|
||||
'differential-toc-ftype center',
|
||||
'differential-toc-file wide',
|
||||
'differential-toc-cov',
|
||||
'differential-toc-cov',
|
||||
))
|
||||
->setDeviceVisibility(
|
||||
array(
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
));
|
||||
|
||||
$anchor = id(new PhabricatorAnchorView())
|
||||
->setAnchorName('toc')
|
||||
->setNavigationMarker(true);
|
||||
|
||||
return id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Table of Contents'))
|
||||
->setTable($table)
|
||||
->appendChild($anchor)
|
||||
->appendChild($buttons);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue