diff --git a/src/applications/pholio/controller/PholioInlineController.php b/src/applications/pholio/controller/PholioInlineController.php index 2a17af1bb7..385c4d4a43 100644 --- a/src/applications/pholio/controller/PholioInlineController.php +++ b/src/applications/pholio/controller/PholioInlineController.php @@ -1,47 +1,46 @@ id = $data['id']; } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $inline_comments = id(new PholioTransactionComment())->loadAllWhere( 'imageid = %d AND (transactionphid IS NOT NULL OR (authorphid = %s AND transactionphid IS NULL))', $this->id, $user->getPHID()); $author_phids = mpull($inline_comments, 'getAuthorPHID'); $authors = $this->loadViewerHandles($author_phids); $inlines = array(); + $engine = new PhabricatorMarkupEngine(); + foreach ($inline_comments as $inline_comment) { $inline_view = id(new PholioInlineCommentView()) + ->setUser($user) ->setHandle($authors[$inline_comment->getAuthorPHID()]) - ->setInlineComment($inline_comment); - - if ($inline_comment->getEditPolicy(PhabricatorPolicyCapability::CAN_EDIT) - == $user->getPHID() && $inline_comment->getTransactionPHID() === null) { - $inline_view->setEditable(true); - } + ->setInlineComment($inline_comment) + ->setEngine($engine); $inlines[] = $inline_comment->toDictionary() + array( 'contentHTML' => $inline_view->render(), ); } return id(new AphrontAjaxResponse())->setContent($inlines); } } diff --git a/src/applications/pholio/controller/PholioInlineSaveController.php b/src/applications/pholio/controller/PholioInlineSaveController.php index 087cbbbaa3..f1d87249d7 100644 --- a/src/applications/pholio/controller/PholioInlineSaveController.php +++ b/src/applications/pholio/controller/PholioInlineSaveController.php @@ -1,102 +1,102 @@ operation; } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $mock = id(new PholioMockQuery()) ->setViewer($user) ->withIDs(array($request->getInt('mockID'))) ->executeOne(); if (!$mock) { return new Aphront404Response(); } $this->operation = $request->getBool('op'); if ($this->getOperation() == 'save') { $new_content = $request->getStr('comment'); if (strlen(trim($new_content)) == 0) { return id(new AphrontAjaxResponse()) ->setContent(array('success' => false)); } $draft = id(new PholioTransactionComment()); $draft->setImageID($request->getInt('imageID')); $draft->setX($request->getInt('startX')); $draft->setY($request->getInt('startY')); $draft->setCommentVersion(1); $draft->setAuthorPHID($user->getPHID()); $draft->setEditPolicy($user->getPHID()); $draft->setViewPolicy(PhabricatorPolicies::POLICY_PUBLIC); $content_source = PhabricatorContentSource::newForSource( PhabricatorContentSource::SOURCE_WEB, array( 'ip' => $request->getRemoteAddr(), )); $draft->setContentSource($content_source); $draft->setWidth($request->getInt('endX') - $request->getInt('startX')); $draft->setHeight($request->getInt('endY') - $request->getInt('startY')); $draft->setContent($new_content); $draft->save(); + $handle = head($this->loadViewerHandles(array($user->getPHID()))); + $inline_view = id(new PholioInlineCommentView()) ->setInlineComment($draft) - ->setEditable(true) - ->setHandle( - PhabricatorObjectHandleData::loadOneHandle( - $user->getPHID(), - $user)); + ->setEngine(new PhabricatorMarkupEngine()) + ->setUser($user) + ->setHandle($handle); return id(new AphrontAjaxResponse()) ->setContent( $draft->toDictionary() + array( 'contentHTML' => $inline_view->render(), )); } else { $dialog = new PholioInlineCommentSaveView(); $dialog->setUser($user); $dialog->setSubmitURI($request->getRequestURI()); $dialog->setTitle(pht('Make inline comment')); $dialog->addHiddenInput('op', 'save'); $dialog->appendChild($this->renderTextArea('')); return id(new AphrontAjaxResponse())->setContent($dialog->render()); } } private function renderTextArea($text) { return javelin_tag( 'textarea', array( 'class' => 'pholio-inline-comment-dialog-textarea', 'name' => 'text', ), $text); } } diff --git a/src/applications/pholio/controller/PholioInlineViewController.php b/src/applications/pholio/controller/PholioInlineViewController.php index 886e61f57a..42028f3b21 100644 --- a/src/applications/pholio/controller/PholioInlineViewController.php +++ b/src/applications/pholio/controller/PholioInlineViewController.php @@ -1,38 +1,34 @@ id = $data['id']; } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $inline_comment = id(new PholioTransactionComment())->load($this->id); - $handle = PhabricatorObjectHandleData::loadOneHandle( - $inline_comment->getAuthorPHID(), - $user); + $handle = head($this->loadViewerHandles( + array($inline_comment->getAuthorPHID()))); $inline_view = id(new PholioInlineCommentView()) + ->setUser($user) ->setHandle($handle) - ->setInlineComment($inline_comment); - - if ($inline_comment->getEditPolicy(PhabricatorPolicyCapability::CAN_EDIT) - == $user->getPHID() && $inline_comment->getTransactionPHID() === null) { - $inline_view->setEditable(true); - } + ->setInlineComment($inline_comment) + ->setEngine(new PhabricatorMarkupEngine()); return id(new AphrontAjaxResponse())->setContent( $inline_comment->toDictionary() + array( 'contentHTML' => $inline_view->render(), )); } } diff --git a/src/applications/pholio/storage/PholioMock.php b/src/applications/pholio/storage/PholioMock.php index 739efa612e..11bfa75031 100644 --- a/src/applications/pholio/storage/PholioMock.php +++ b/src/applications/pholio/storage/PholioMock.php @@ -1,155 +1,161 @@ true, ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID('MOCK'); } public function save() { if (!$this->getMailKey()) { $this->setMailKey(Filesystem::readRandomCharacters(20)); } return parent::save(); } public function attachImages(array $images) { assert_instances_of($images, 'PholioImage'); $this->images = $images; return $this; } public function getImages() { if ($this->images === null) { throw new Exception("Call attachImages() before getImages()!"); } return $this->images; } public function attachCoverFile(PhabricatorFile $file) { $this->coverFile = $file; return $this; } public function getCoverFile() { if ($this->coverFile === null) { throw new Exception("Call attachCoverFile() before getCoverFile()!"); } return $this->coverFile; } /* -( PhabricatorSubscribableInterface Implementation )-------------------- */ public function isAutomaticallySubscribed($phid) { return ($this->authorPHID == $phid); } /* -( PhabricatorPolicyInterface Implementation )-------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return $this->getViewPolicy(); case PhabricatorPolicyCapability::CAN_EDIT: return PhabricatorPolicies::POLICY_NOONE; } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return ($viewer->getPHID() == $this->getAuthorPHID()); } /* -( PhabricatorMarkupInterface )----------------------------------------- */ public function getMarkupFieldKey($field) { $hash = PhabricatorHash::digest($this->getMarkupText($field)); return 'M:'.$hash; } public function newMarkupEngine($field) { return PhabricatorMarkupEngine::newMarkupEngine(array()); } public function getMarkupText($field) { if ($this->getDescription()) { $description = $this->getDescription(); } else { $description = pht('No Description Given'); } return $description; } public function didMarkupText($field, $output, PhutilMarkupEngine $engine) { - return $output; + require_celerity_resource('phabricator-remarkup-css'); + return phutil_tag( + 'div', + array( + 'class' => 'phabricator-remarkup', + ), + $output); } public function shouldUseMarkupCache($field) { return (bool)$this->getID(); } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new PholioMockEditor(); } public function getApplicationTransactionObject() { return new PholioTransaction(); } /* -( PhabricatorTokenReceiverInterface )---------------------------------- */ public function getUsersToNotifyOfTokenGiven() { return array( $this->getAuthorPHID(), ); } } diff --git a/src/applications/pholio/storage/PholioTransactionComment.php b/src/applications/pholio/storage/PholioTransactionComment.php index ec4ebe4954..4517157a51 100644 --- a/src/applications/pholio/storage/PholioTransactionComment.php +++ b/src/applications/pholio/storage/PholioTransactionComment.php @@ -1,31 +1,36 @@ $this->getID(), 'phid' => $this->getPHID(), 'transactionphid' => $this->getTransactionPHID(), 'x' => $this->getX(), 'y' => $this->getY(), 'width' => $this->getWidth(), 'height' => $this->getHeight(), ); } + public function shouldUseMarkupCache($field) { + // Only cache submitted comments. + return ($this->getTransactionPHID() != null); + } } diff --git a/src/applications/pholio/view/PholioInlineCommentView.php b/src/applications/pholio/view/PholioInlineCommentView.php index eb2707083f..2fa0bd8515 100644 --- a/src/applications/pholio/view/PholioInlineCommentView.php +++ b/src/applications/pholio/view/PholioInlineCommentView.php @@ -1,99 +1,114 @@ engine = $engine; + return $this; + } + + public function setHandle(PhabricatorObjectHandle $handle) { + $this->handle = $handle; + return $this; + } public function setInlineComment(PholioTransactionComment $inline_comment) { if ($inline_comment->getImageID() === null) { throw new Exception("Comment provided is not inline comment"); } $this->inlineComment = $inline_comment; return $this; } - public function setHandle(PhabricatorObjectHandle $handle) { - $this->handle = $handle; - return $this; - } - - public function setEditable($editable) { - $this->editable = $editable; - return $this; - } - public function render() { if (!$this->inlineComment) { throw new Exception("Call setInlineComment() before render()!"); } + if ($this->user === null) { + throw new Exception("Call setUser() before render()!"); + } + if ($this->engine === null) { + throw new Exception("Call setEngine() before render()!"); + } + if ($this->handle === null) { + throw new Exception("Call setHandle() before render()!"); + } $actions = null; - if ($this->editable) { + if ($this->inlineComment->getTransactionPHID() === null && + $this->inlineComment->getEditPolicy( + PhabricatorPolicyCapability::CAN_EDIT) == $this->user->getPHID()) { + $edit_action = javelin_tag( 'a', array( 'href' => '/pholio/inline/edit/'.$this->inlineComment->getID(), 'sigil' => 'inline-edit', 'meta' => array( 'phid' => $this->inlineComment->getPHID(), 'id' => $this->inlineComment->getID() ) ), pht('Edit')); $delete_action = javelin_tag( 'a', array( 'href' => '/pholio/inline/delete/'.$this->inlineComment->getID(), 'sigil' => 'inline-delete', 'meta' => array( 'phid' => $this->inlineComment->getPHID(), 'id' => $this->inlineComment->getID() ) ), pht('Delete')); $actions = phutil_tag( 'span', array( 'class' => 'pholio-inline-head-links' ), array($edit_action, $delete_action)); } $comment_header = phutil_tag( 'div', array( 'class' => 'pholio-inline-comment-header' ), array($this->handle->getName(), $actions)); + + $comment = $this->engine->renderOneObject( + $this->inlineComment, + PholioTransactionComment::MARKUP_FIELD_COMMENT, + $this->user); + $comment_body = phutil_tag( 'div', - array( - - ), - $this->inlineComment->getContent()); + array(), + $comment); $comment_block = javelin_tag( 'div', array( 'id' => $this->inlineComment->getPHID()."_comment", 'class' => 'pholio-inline-comment', 'sigil' => 'inline_comment', 'meta' => array( 'phid' => $this->inlineComment->getPHID() ) ), array($comment_header, $comment_body)); return $this->renderSingleView($comment_block); } } diff --git a/src/applications/pholio/view/PholioMockImagesView.php b/src/applications/pholio/view/PholioMockImagesView.php index 1764244dd5..8ff70e96f3 100644 --- a/src/applications/pholio/view/PholioMockImagesView.php +++ b/src/applications/pholio/view/PholioMockImagesView.php @@ -1,119 +1,119 @@ mock = $mock; return $this; } public function render() { if (!$this->mock) { throw new Exception("Call setMock() before render()!"); } $mock = $this->mock; require_celerity_resource('javelin-behavior-pholio-mock-view'); $images = array(); $panel_id = celerity_generate_unique_node_id(); $viewport_id = celerity_generate_unique_node_id(); foreach ($mock->getImages() as $image) { $images[] = array( 'id' => $image->getID(), 'fullURI' => $image->getFile()->getBestURI(), ); } $config = array( 'mockID' => $mock->getID(), 'panelID' => $panel_id, 'viewportID' => $viewport_id, 'images' => $images, ); Javelin::initBehavior('pholio-mock-view', $config); $mockview = ''; $mock_wrapper = phutil_tag( 'div', array( 'id' => $viewport_id, 'class' => 'pholio-mock-image-viewport' ), ''); $mock_wrapper = javelin_tag( 'div', array( 'id' => $panel_id, 'sigil' => 'mock-panel', 'class' => 'pholio-mock-image-panel', ), $mock_wrapper); $inline_comments_holder = javelin_tag( 'div', array( 'id' => 'mock-inline-comments', 'sigil' => 'mock-inline-comments', 'class' => 'pholio-mock-inline-comments' ), ''); $mockview[] = phutil_tag( 'div', array( 'class' => 'pholio-mock-image-container', 'id' => 'pholio-mock-image-container' ), array($mock_wrapper, $inline_comments_holder)); - if (count($mock->getImages()) > 1) { + if (count($mock->getImages()) > 0) { $thumbnails = array(); foreach ($mock->getImages() as $image) { $thumbfile = $image->getFile(); $dimensions = PhabricatorImageTransformer::getPreviewDimensions( $thumbfile, 140); $tag = phutil_tag( 'img', array( 'width' => $dimensions['sdx'], 'height' => $dimensions['sdy'], 'src' => $thumbfile->getPreview140URI(), 'class' => 'pholio-mock-carousel-thumbnail', 'style' => 'top: '.floor((140 - $dimensions['sdy'] ) / 2).'px', )); $thumbnails[] = javelin_tag( 'div', array( 'sigil' => 'mock-thumbnail', 'class' => 'pholio-mock-carousel-thumb-item', 'meta' => array( 'imageID' => $image->getID(), ), ), $tag); } $mockview[] = phutil_tag( 'div', array( 'id' => 'pholio-mock-carousel', 'class' => 'pholio-mock-carousel', ), $thumbnails); } return $this->renderSingleView($mockview); } }