Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/pholio/controller/PholioMockViewController.php b/src/applications/pholio/controller/PholioMockViewController.php
index 00d003baca..92016d0a63 100644
--- a/src/applications/pholio/controller/PholioMockViewController.php
+++ b/src/applications/pholio/controller/PholioMockViewController.php
@@ -1,233 +1,233 @@
<?php
final class PholioMockViewController extends PholioController {
private $id;
private $imageID;
private $maniphestTaskPHIDs = array();
private function setManiphestTaskPHIDs($maniphest_task_phids) {
$this->maniphestTaskPHIDs = $maniphest_task_phids;
return $this;
}
private function getManiphestTaskPHIDs() {
return $this->maniphestTaskPHIDs;
}
public function shouldAllowPublic() {
return true;
}
public function willProcessRequest(array $data) {
$this->id = $data['id'];
$this->imageID = idx($data, 'imageID');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$mock = id(new PholioMockQuery())
->setViewer($user)
->withIDs(array($this->id))
->needImages(true)
- ->needCoverFiles(true)
+ ->needInlineComments(true)
->executeOne();
if (!$mock) {
return new Aphront404Response();
}
$xactions = id(new PholioTransactionQuery())
->setViewer($user)
->withObjectPHIDs(array($mock->getPHID()))
->execute();
$phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$mock->getPHID(),
PhabricatorEdgeConfig::TYPE_MOCK_HAS_TASK);
$this->setManiphestTaskPHIDs($phids);
$phids[] = $mock->getAuthorPHID();
$this->loadHandles($phids);
$engine = id(new PhabricatorMarkupEngine())
->setViewer($user);
$engine->addObject($mock, PholioMock::MARKUP_FIELD_DESCRIPTION);
foreach ($xactions as $xaction) {
if ($xaction->getComment()) {
$engine->addObject(
$xaction->getComment(),
PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
}
}
$engine->process();
$title = $mock->getName();
if ($mock->isClosed()) {
$header_icon = 'fa-ban';
$header_name = pht('Closed');
$header_color = 'dark';
} else {
$header_icon = 'fa-square-o';
$header_name = pht('Open');
$header_color = 'bluegrey';
}
$header = id(new PHUIHeaderView())
->setHeader($title)
->setUser($user)
->setStatus($header_icon, $header_color, $header_name)
->setPolicyObject($mock);
$actions = $this->buildActionView($mock);
$properties = $this->buildPropertyView($mock, $engine, $actions);
require_celerity_resource('pholio-css');
require_celerity_resource('pholio-inline-comments-css');
$comment_form_id = celerity_generate_unique_node_id();
$output = id(new PholioMockImagesView())
->setRequestURI($request->getRequestURI())
->setCommentFormID($comment_form_id)
->setUser($user)
->setMock($mock)
->setImageID($this->imageID);
$output = id(new PHUIObjectBoxView())
->setHeaderText(pht('Image'))
->appendChild($output);
$xaction_view = id(new PholioTransactionView())
->setUser($this->getRequest()->getUser())
->setObjectPHID($mock->getPHID())
->setTransactions($xactions)
->setMarkupEngine($engine);
$add_comment = $this->buildAddCommentView($mock, $comment_form_id);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->setActionList($actions);
$crumbs->addTextCrumb('M'.$mock->getID(), '/M'.$mock->getID());
$object_box = id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
$thumb_grid = id(new PholioMockThumbGridView())
->setUser($user)
->setMock($mock);
$content = array(
$crumbs,
$object_box,
$output,
phutil_tag('br'),
$thumb_grid,
$xaction_view,
$add_comment,
);
return $this->buildApplicationPage(
$content,
array(
'title' => 'M'.$mock->getID().' '.$title,
'device' => true,
'pageObjects' => array($mock->getPHID()),
));
}
private function buildActionView(PholioMock $mock) {
$user = $this->getRequest()->getUser();
$actions = id(new PhabricatorActionListView())
->setUser($user)
->setObjectURI($this->getRequest()->getRequestURI())
->setObject($mock);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$user,
$mock,
PhabricatorPolicyCapability::CAN_EDIT);
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setName(pht('Edit Mock'))
->setHref($this->getApplicationURI('/edit/'.$mock->getID().'/'))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
$actions->addAction(
id(new PhabricatorActionView())
->setIcon('fa-anchor')
->setName(pht('Edit Maniphest Tasks'))
->setHref("/search/attach/{$mock->getPHID()}/TASK/edge/")
->setDisabled(!$user->isLoggedIn())
->setWorkflow(true));
return $actions;
}
private function buildPropertyView(
PholioMock $mock,
PhabricatorMarkupEngine $engine,
PhabricatorActionListView $actions) {
$user = $this->getRequest()->getUser();
$properties = id(new PHUIPropertyListView())
->setUser($user)
->setObject($mock)
->setActionList($actions);
$properties->addProperty(
pht('Author'),
$this->getHandle($mock->getAuthorPHID())->renderLink());
$properties->addProperty(
pht('Created'),
phabricator_datetime($mock->getDateCreated(), $user));
if ($this->getManiphestTaskPHIDs()) {
$properties->addProperty(
pht('Maniphest Tasks'),
$this->renderHandlesForPHIDs($this->getManiphestTaskPHIDs()));
}
$properties->invokeWillRenderEvent();
$properties->addSectionHeader(
pht('Description'),
PHUIPropertyListView::ICON_SUMMARY);
$properties->addImageContent(
$engine->getOutput($mock, PholioMock::MARKUP_FIELD_DESCRIPTION));
return $properties;
}
private function buildAddCommentView(PholioMock $mock, $comment_form_id) {
$user = $this->getRequest()->getUser();
$draft = PhabricatorDraft::newFromUserAndKey($user, $mock->getPHID());
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
$title = $is_serious
? pht('Add Comment')
: pht('History Beckons');
$form = id(new PhabricatorApplicationTransactionCommentView())
->setUser($user)
->setObjectPHID($mock->getPHID())
->setFormID($comment_form_id)
->setDraft($draft)
->setHeaderText($title)
->setSubmitButtonName(pht('Add Comment'))
->setAction($this->getApplicationURI('/comment/'.$mock->getID().'/'))
->setRequestURI($this->getRequest()->getRequestURI());
return $form;
}
}
diff --git a/src/applications/pholio/view/PholioMockThumbGridView.php b/src/applications/pholio/view/PholioMockThumbGridView.php
index 662a43447c..ced0fe73b0 100644
--- a/src/applications/pholio/view/PholioMockThumbGridView.php
+++ b/src/applications/pholio/view/PholioMockThumbGridView.php
@@ -1,136 +1,149 @@
<?php
final class PholioMockThumbGridView extends AphrontView {
private $mock;
public function setMock(PholioMock $mock) {
$this->mock = $mock;
return $this;
}
public function render() {
$mock = $this->mock;
$all_images = $mock->getAllImages();
$all_images = mpull($all_images, null, 'getPHID');
$history = mpull($all_images, 'getReplacesImagePHID', 'getPHID');
$replaced = array();
foreach ($history as $phid => $replaces_phid) {
if ($replaces_phid) {
$replaced[$replaces_phid] = true;
}
}
// Figure out the columns. Start with all the active images.
$images = mpull($mock->getImages(), null, 'getPHID');
// Now, find deleted images: obsolete images which were not replaced.
foreach ($mock->getAllImages() as $image) {
if (!$image->getIsObsolete()) {
// Image is current.
continue;
}
if (isset($replaced[$image->getPHID()])) {
// Image was replaced.
continue;
}
// This is an obsolete image which was not replaced, so it must be
// a deleted image.
$images[$image->getPHID()] = $image;
}
$cols = array();
$depth = 0;
foreach ($images as $image) {
$phid = $image->getPHID();
$col = array();
// If this is a deleted image, null out the final column.
if ($image->getIsObsolete()) {
$col[] = null;
}
$col[] = $phid;
while ($phid && isset($history[$phid])) {
$col[] = $history[$phid];
$phid = $history[$phid];
}
$cols[] = $col;
$depth = max($depth, count($col));
}
$grid = array();
for ($ii = 0; $ii < $depth; $ii++) {
$row = array();
foreach ($cols as $col) {
if (empty($col[$ii])) {
$row[] = phutil_tag('td', array(), null);
} else {
$thumb = $this->renderThumbnail($all_images[$col[$ii]]);
$row[] = phutil_tag('td', array(), $thumb);
}
}
$grid[] = phutil_tag('tr', array(), $row);
}
$grid = phutil_tag(
'table',
array(
'id' => 'pholio-mock-thumb-grid',
'class' => 'pholio-mock-thumb-grid',
),
$grid);
$grid = id(new PHUIBoxView())
->addClass('pholio-mock-thumb-grid-container')
->appendChild($grid);
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Mock History'))
->appendChild($grid);
}
private function renderThumbnail(PholioImage $image) {
$thumbfile = $image->getFile();
$dimensions = PhabricatorImageTransformer::getPreviewDimensions(
$thumbfile,
100);
$tag = phutil_tag(
'img',
array(
'width' => $dimensions['sdx'],
'height' => $dimensions['sdy'],
'src' => $thumbfile->getPreview100URI(),
'class' => 'pholio-mock-thumb-grid-image',
'style' => 'top: '.floor((100 - $dimensions['sdy'] ) / 2).'px',
));
$classes = array('pholio-mock-thumb-grid-item');
if ($image->getIsObsolete()) {
$classes[] = 'pholio-mock-thumb-grid-item-obsolete';
}
+ $inline_count = null;
+ if ($image->getInlineComments()) {
+ $inline_count[] = phutil_tag(
+ 'span',
+ array(
+ 'class' => 'pholio-mock-thumb-grid-comment-count',
+ ),
+ pht('%s', new PhutilNumber(count($image->getInlineComments()))));
+ }
+
return javelin_tag(
'a',
array(
'sigil' => 'mock-thumbnail',
'class' => implode(' ', $classes),
'href' => '#',
'meta' => array(
'imageID' => $image->getID(),
),
),
- $tag);
+ array(
+ $tag,
+ $inline_count,
+ ));
}
}
diff --git a/webroot/rsrc/css/application/pholio/pholio.css b/webroot/rsrc/css/application/pholio/pholio.css
index ba56163eb6..5efdd987bd 100644
--- a/webroot/rsrc/css/application/pholio/pholio.css
+++ b/webroot/rsrc/css/application/pholio/pholio.css
@@ -1,154 +1,169 @@
/**
* @provides pholio-css
*/
.pholio-mock-image-container {
text-align: center;
vertical-align: middle;
position: relative;
background: url('/rsrc/image/checker_lighter.png');
}
.pholio-mock-thumb-grid-container {
padding: 12px;
overflow-x: auto;
overflow-y: hidden;
}
.pholio-mock-thumb-grid {
margin: 0 auto;
}
.pholio-mock-thumb-grid-item {
display: inline-block;
cursor: pointer;
width: 100px;
height: 100px;
padding: 4px;
margin: 4px;
vertical-align: middle;
border: 1px solid {$lightgreyborder};
position: relative;
background: url('/rsrc/image/checker_lighter.png');
}
.device-desktop .pholio-mock-thumb-grid-item:hover {
border-color: {$indigo};
}
.pholio-mock-thumb-grid-current {
border-color: {$sky};
}
.pholio-mock-thumb-grid-item-obsolete {
opacity: 0.5;
}
.pholio-mock-thumb-grid-image {
margin: auto;
position: relative;
}
.pholio-mock-image {
margin: auto;
cursor: crosshair;
}
.pholio-mock-image-viewport {
position: relative;
margin: auto;
display: inline-block;
}
.pholio-image-loading img {
opacity: 0.50;
}
.pholio-image-info-item {
padding: 0 8px;
margin: 8px 0;
}
.pholio-visible-size {
color: {$sky};
font-weight: bold;
}
.pholio-device-lightbox {
position: absolute;
overflow: auto;
}
.pholio-device-lightbox img {
display: block;
margin: auto;
}
.pholio-device-lightbox-loading {
background: url(/rsrc/image/darkload.gif) no-repeat center;
}
.pholio-transaction-inline-comment {
display: table-row;
}
.pholio-transaction-inline-comment img {
display: table-cell;
padding-bottom: 2px;
}
.pholio-transaction-inline-comment span {
display: table-cell;
vertical-align: middle;
padding-left: 8px;
}
.pholio-mock-reticle {
position: absolute;
display: none;
box-sizing: border-box;
}
.pholio-mock-reticle-selection {
background-color: rgba(255, 255, 255, 0.50);
border: 1px dashed #000;
}
.pholio-mock-reticle-draft {
font-size: 2.2em;
color: {$yellow};
text-shadow: 0 3px 8px rgba(0, 0, 0, 0.35);
-webkit-text-stroke: 1px white;
}
.pholio-mock-reticle-final {
font-size: 2.2em;
color: {$indigo};
text-shadow: 0 3px 8px rgba(0, 0, 0, 0.35);
-webkit-text-stroke: 1px white;
}
.pholio-mock-reticle-draft:hover,
.pholio-mock-reticle-final:hover {
background-color: rgba(255, 255, 255, 0.50);
cursor: pointer;
}
.device-desktop .mock-has-cursor .pholio-mock-reticle {
display: block;
}
.pholio-mock-image-header {
position: absolute;
top: 0;
right: 0;
font-size: 14px;
padding: 4px 8px;
background: rgba(255,255,255,.6);
color: {$greytext};
}
.pholio-image-title {
font-weight: bold;
color: {$bluetext};
}
+
+.pholio-mock-thumb-grid-comment-count {
+ position: absolute;
+ right: 4px;
+ bottom: 4px;
+ width: 20px;
+ height: 20px;
+ text-align: center;
+ line-height: 20px;
+ border-radius: 10px;
+ font-weight: bold;
+ color: #fff;
+ text-decoration: none;
+ background: {$indigo};
+}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Nov 5, 5:20 PM (1 d, 1 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
321178
Default Alt Text
(14 KB)

Event Timeline