1
0
Fork 0
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:
epriestley 2015-08-15 11:43:12 -07:00
parent fca716d699
commit cb912d1735
4 changed files with 412 additions and 10 deletions

View file

@ -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',

View file

@ -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;
}
}

View 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);
}
}

View file

@ -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);
}
}