@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Remove inline gutter in Pholio

Summary: This greatly simplifies inline comments while retaining their functionality. This is probably not where we want to end up, but will let us figure out what we're doing with the stage without worrying about inlines.

Test Plan: See screenshots.

Reviewers: chad

Reviewed By: chad

Subscribers: epriestley

Differential Revision: https://secure.phabricator.com/D9537

+252 -932
+24 -24
resources/celerity/map.php
··· 81 81 'rsrc/css/application/phame/phame.css' => '19ecc703', 82 82 'rsrc/css/application/pholio/pholio-edit.css' => 'b9e59b6d', 83 83 'rsrc/css/application/pholio/pholio-inline-comments.css' => '28a2e394', 84 - 'rsrc/css/application/pholio/pholio.css' => 'cea40026', 84 + 'rsrc/css/application/pholio/pholio.css' => 'cabb65b3', 85 85 'rsrc/css/application/phortune/phortune-credit-card-form.css' => 'b25b4beb', 86 86 'rsrc/css/application/phrequent/phrequent.css' => 'ffc185ad', 87 87 'rsrc/css/application/phriction/phriction-document-css.css' => '7d7f0071', ··· 389 389 'rsrc/js/application/passphrase/phame-credential-control.js' => '1e1c8a59', 390 390 'rsrc/js/application/phame/phame-post-preview.js' => '61d927ec', 391 391 'rsrc/js/application/pholio/behavior-pholio-mock-edit.js' => '1e1e8bb0', 392 - 'rsrc/js/application/pholio/behavior-pholio-mock-view.js' => '9cc93707', 392 + 'rsrc/js/application/pholio/behavior-pholio-mock-view.js' => '0c8a037a', 393 393 'rsrc/js/application/phortune/behavior-balanced-payment-form.js' => '3b3e1664', 394 394 'rsrc/js/application/phortune/behavior-stripe-payment-form.js' => '1693a296', 395 395 'rsrc/js/application/phortune/behavior-test-payment-form.js' => 'b3e5ee60', ··· 613 613 'javelin-behavior-phabricator-watch-anchor' => '06e05112', 614 614 'javelin-behavior-phame-post-preview' => '61d927ec', 615 615 'javelin-behavior-pholio-mock-edit' => '1e1e8bb0', 616 - 'javelin-behavior-pholio-mock-view' => '9cc93707', 616 + 'javelin-behavior-pholio-mock-view' => '0c8a037a', 617 617 'javelin-behavior-phui-object-box-tabs' => 'a3e2244e', 618 618 'javelin-behavior-phui-timeline-dropdown-menu' => '4d94d9c3', 619 619 'javelin-behavior-policy-control' => 'f3fef818', ··· 739 739 'phabricator-uiexample-reactor-sendproperties' => '551add57', 740 740 'phabricator-zindex-css' => 'efb673ac', 741 741 'phame-css' => '19ecc703', 742 - 'pholio-css' => 'cea40026', 742 + 'pholio-css' => 'cabb65b3', 743 743 'pholio-edit-css' => 'b9e59b6d', 744 744 'pholio-inline-comments-css' => '28a2e394', 745 745 'phortune-credit-card-form' => '2290aeef', ··· 896 896 3 => 'javelin-util', 897 897 4 => 'phabricator-notification-css', 898 898 ), 899 + '0c8a037a' => 900 + array( 901 + 0 => 'javelin-behavior', 902 + 1 => 'javelin-util', 903 + 2 => 'javelin-stratcom', 904 + 3 => 'javelin-dom', 905 + 4 => 'javelin-vector', 906 + 5 => 'javelin-magical-init', 907 + 6 => 'javelin-request', 908 + 7 => 'javelin-history', 909 + 8 => 'javelin-workflow', 910 + 9 => 'javelin-mask', 911 + 10 => 'javelin-behavior-device', 912 + 11 => 'phabricator-keyboard-shortcut', 913 + ), 899 914 '0e34ca02' => 900 915 array( 901 916 0 => 'javelin-behavior', ··· 1254 1269 2 => 'javelin-util', 1255 1270 3 => 'phabricator-shaped-request', 1256 1271 ), 1257 - '7319e029' => 1258 - array( 1259 - 0 => 'javelin-behavior', 1260 - 1 => 'javelin-dom', 1261 - ), 1262 1272 '62e18640' => 1263 1273 array( 1264 1274 0 => 'javelin-install', ··· 1330 1340 0 => 'javelin-behavior', 1331 1341 1 => 'javelin-stratcom', 1332 1342 2 => 'javelin-dom', 1343 + ), 1344 + '7319e029' => 1345 + array( 1346 + 0 => 'javelin-behavior', 1347 + 1 => 'javelin-dom', 1333 1348 ), 1334 1349 '76f4ebed' => 1335 1350 array( ··· 1526 1541 2 => 'javelin-stratcom', 1527 1542 3 => 'javelin-vector', 1528 1543 4 => 'phabricator-hovercard', 1529 - ), 1530 - '9cc93707' => 1531 - array( 1532 - 0 => 'javelin-behavior', 1533 - 1 => 'javelin-util', 1534 - 2 => 'javelin-stratcom', 1535 - 3 => 'javelin-dom', 1536 - 4 => 'javelin-vector', 1537 - 5 => 'javelin-magical-init', 1538 - 6 => 'javelin-request', 1539 - 7 => 'javelin-history', 1540 - 8 => 'javelin-workflow', 1541 - 9 => 'javelin-mask', 1542 - 10 => 'javelin-behavior-device', 1543 - 11 => 'phabricator-keyboard-shortcut', 1544 1544 ), 1545 1545 '9db3d160' => 1546 1546 array(
+2 -14
src/__phutil_library_map__.php
··· 2413 2413 'PholioImageHistoryController' => 'applications/pholio/controller/PholioImageHistoryController.php', 2414 2414 'PholioImageQuery' => 'applications/pholio/query/PholioImageQuery.php', 2415 2415 'PholioImageUploadController' => 'applications/pholio/controller/PholioImageUploadController.php', 2416 - 'PholioInlineCommentEditView' => 'applications/pholio/view/PholioInlineCommentEditView.php', 2417 - 'PholioInlineCommentSaveView' => 'applications/pholio/view/PholioInlineCommentSaveView.php', 2418 - 'PholioInlineCommentView' => 'applications/pholio/view/PholioInlineCommentView.php', 2419 2416 'PholioInlineController' => 'applications/pholio/controller/PholioInlineController.php', 2420 - 'PholioInlineDeleteController' => 'applications/pholio/controller/PholioInlineDeleteController.php', 2421 - 'PholioInlineEditController' => 'applications/pholio/controller/PholioInlineEditController.php', 2422 - 'PholioInlineSaveController' => 'applications/pholio/controller/PholioInlineSaveController.php', 2417 + 'PholioInlineListController' => 'applications/pholio/controller/PholioInlineListController.php', 2423 2418 'PholioInlineThumbController' => 'applications/pholio/controller/PholioInlineThumbController.php', 2424 - 'PholioInlineViewController' => 'applications/pholio/controller/PholioInlineViewController.php', 2425 2419 'PholioMock' => 'applications/pholio/storage/PholioMock.php', 2426 2420 'PholioMockCommentController' => 'applications/pholio/controller/PholioMockCommentController.php', 2427 2421 'PholioMockEditController' => 'applications/pholio/controller/PholioMockEditController.php', ··· 5321 5315 'PholioImageHistoryController' => 'PholioController', 5322 5316 'PholioImageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 5323 5317 'PholioImageUploadController' => 'PholioController', 5324 - 'PholioInlineCommentEditView' => 'AphrontView', 5325 - 'PholioInlineCommentSaveView' => 'AphrontView', 5326 - 'PholioInlineCommentView' => 'AphrontView', 5327 5318 'PholioInlineController' => 'PholioController', 5328 - 'PholioInlineDeleteController' => 'PholioController', 5329 - 'PholioInlineEditController' => 'PholioController', 5330 - 'PholioInlineSaveController' => 'PholioController', 5319 + 'PholioInlineListController' => 'PholioController', 5331 5320 'PholioInlineThumbController' => 'PholioController', 5332 - 'PholioInlineViewController' => 'PholioController', 5333 5321 'PholioMock' => 5334 5322 array( 5335 5323 0 => 'PholioDAO',
+2 -5
src/applications/pholio/application/PhabricatorApplicationPholio.php
··· 47 47 'edit/(?P<id>\d+)/' => 'PholioMockEditController', 48 48 'comment/(?P<id>\d+)/' => 'PholioMockCommentController', 49 49 'inline/' => array( 50 - '(?P<id>\d+)/' => 'PholioInlineController', 51 - 'save/' => 'PholioInlineSaveController', 52 - 'delete/(?P<id>\d+)/' => 'PholioInlineDeleteController', 53 - 'view/(?P<id>\d+)/' => 'PholioInlineViewController', 54 - 'edit/(?P<id>\d+)/' => 'PholioInlineEditController', 50 + '(?:(?P<id>\d+)/)?' => 'PholioInlineController', 51 + 'list/(?P<id>\d+)/' => 'PholioInlineListController', 55 52 'thumb/(?P<imageid>\d+)/' => 'PholioInlineThumbController' 56 53 ), 57 54 'image/' => array(
+116 -23
src/applications/pholio/controller/PholioInlineController.php
··· 1 1 <?php 2 2 3 - /** 4 - * @group pholio 5 - */ 6 3 final class PholioInlineController extends PholioController { 7 4 8 5 private $id; 9 6 10 7 public function willProcessRequest(array $data) { 11 - $this->id = $data['id']; 8 + $this->id = idx($data, 'id'); 12 9 } 13 10 14 11 public function processRequest() { 15 12 $request = $this->getRequest(); 16 - $user = $request->getUser(); 13 + $viewer = $request->getUser(); 14 + 15 + if ($this->id) { 16 + $inline = id(new PholioTransactionComment())->load($this->id); 17 + if (!$inline) { 18 + return new Aphront404Response(); 19 + } 20 + 21 + if ($inline->getTransactionPHID()) { 22 + $mode = 'view'; 23 + } else { 24 + if ($inline->getAuthorPHID() == $viewer->getPHID()) { 25 + $mode = 'edit'; 26 + } else { 27 + return new Aphront404Response(); 28 + } 29 + } 30 + } else { 31 + $mock = id(new PholioMockQuery()) 32 + ->setViewer($viewer) 33 + ->withIDs(array($request->getInt('mockID'))) 34 + ->executeOne(); 35 + 36 + if (!$mock) { 37 + return new Aphront404Response(); 38 + } 39 + 40 + $inline = id(new PholioTransactionComment()) 41 + ->setImageID($request->getInt('imageID')) 42 + ->setX($request->getInt('startX')) 43 + ->setY($request->getInt('startY')) 44 + ->setCommentVersion(1) 45 + ->setAuthorPHID($viewer->getPHID()) 46 + ->setEditPolicy($viewer->getPHID()) 47 + ->setViewPolicy(PhabricatorPolicies::POLICY_PUBLIC) 48 + ->setContentSourceFromRequest($request) 49 + ->setWidth($request->getInt('endX') - $request->getInt('startX')) 50 + ->setHeight($request->getInt('endY') - $request->getInt('startY')); 51 + 52 + $mode = 'new'; 53 + } 54 + 55 + $v_content = $inline->getContent(); 56 + 57 + // TODO: Not correct, but we don't always have a mock right now. 58 + $mock_uri = '/'; 59 + 60 + if ($mode == 'view') { 61 + 62 + $handles = $this->loadViewerHandles(array($inline->getAuthorPHID())); 63 + $author_handle = $handles[$inline->getAuthorPHID()]; 64 + 65 + return $this->newDialog() 66 + ->setTitle(pht('Inline Comment')) 67 + ->appendParagraph( 68 + phutil_tag( 69 + 'em', 70 + array(), 71 + pht('%s comments:', $author_handle->getName()))) 72 + ->appendParagraph( 73 + PhabricatorMarkupEngine::renderOneObject( 74 + id(new PhabricatorMarkupOneOff()) 75 + ->setContent($inline->getContent()), 76 + 'default', 77 + $viewer)) 78 + ->addCancelButton($mock_uri, pht('Close')); 79 + } 17 80 18 - $inline_comments = id(new PholioTransactionComment())->loadAllWhere( 19 - 'imageid = %d AND (transactionphid IS NOT NULL 20 - OR (authorphid = %s AND transactionphid IS NULL))', 21 - $this->id, 22 - $user->getPHID()); 81 + if ($request->isFormPost()) { 82 + $v_content = $request->getStr('content'); 23 83 24 - $author_phids = mpull($inline_comments, 'getAuthorPHID'); 25 - $authors = $this->loadViewerHandles($author_phids); 84 + if (strlen($v_content)) { 85 + $inline->setContent($v_content); 86 + $inline->save(); 87 + $dictionary = $inline->toDictionary(); 88 + } else if ($inline->getID()) { 89 + $inline->delete(); 90 + $dictionary = array(); 91 + } 26 92 27 - $inlines = array(); 93 + return id(new AphrontAjaxResponse())->setContent($dictionary); 94 + } 28 95 29 - $engine = new PhabricatorMarkupEngine(); 96 + switch ($mode) { 97 + case 'edit': 98 + $title = pht('Edit Inline Comment'); 99 + $submit_text = pht('Save Draft'); 100 + break; 101 + case 'new': 102 + $title = pht('New Inline Comment'); 103 + $submit_text = pht('Save Draft'); 104 + break; 105 + } 30 106 31 - foreach ($inline_comments as $inline_comment) { 32 - $inline_view = id(new PholioInlineCommentView()) 33 - ->setUser($user) 34 - ->setHandle($authors[$inline_comment->getAuthorPHID()]) 35 - ->setInlineComment($inline_comment) 36 - ->setEngine($engine); 107 + $form = id(new AphrontFormView()) 108 + ->setUser($viewer); 37 109 38 - $inlines[] = $inline_comment->toDictionary() + array( 39 - 'contentHTML' => $inline_view->render(), 110 + if ($mode == 'new') { 111 + $params = array( 112 + 'mockID' => $request->getInt('mockID'), 113 + 'imageID' => $request->getInt('imageID'), 114 + 'startX' => $request->getInt('startX'), 115 + 'startY' => $request->getInt('startY'), 116 + 'endX' => $request->getInt('endX'), 117 + 'endY' => $request->getInt('endY'), 40 118 ); 119 + foreach ($params as $key => $value) { 120 + $form->addHiddenInput($key, $value); 121 + } 41 122 } 42 123 43 - return id(new AphrontAjaxResponse())->setContent($inlines); 124 + $form 125 + ->appendChild( 126 + id(new PhabricatorRemarkupControl()) 127 + ->setName('content') 128 + ->setLabel(pht('Comment')) 129 + ->setValue($v_content)); 130 + 131 + return $this->newDialog() 132 + ->setTitle($title) 133 + ->setWidth(AphrontDialogView::WIDTH_FORM) 134 + ->appendChild($form->buildLayoutView()) 135 + ->addCancelButton($mock_uri) 136 + ->addSubmitButton($submit_text); 44 137 } 45 138 46 139 }
-34
src/applications/pholio/controller/PholioInlineDeleteController.php
··· 1 - <?php 2 - 3 - /** 4 - * @group pholio 5 - */ 6 - final class PholioInlineDeleteController extends PholioController { 7 - 8 - private $id; 9 - 10 - public function willProcessRequest(array $data) { 11 - $this->id = $data['id']; 12 - } 13 - 14 - public function processRequest() { 15 - $request = $this->getRequest(); 16 - $user = $request->getUser(); 17 - 18 - $inline_comment = id(new PholioTransactionComment())->loadOneWhere( 19 - 'id = %d AND authorphid = %s AND transactionphid IS NULL', 20 - $this->id, 21 - $user->getPHID()); 22 - 23 - if ($inline_comment == null) { 24 - return new Aphront404Response(); 25 - } else { 26 - 27 - $inline_comment->delete(); 28 - return id(new AphrontAjaxResponse()) 29 - ->setContent(array('success' => true)); 30 - } 31 - 32 - } 33 - 34 - }
-82
src/applications/pholio/controller/PholioInlineEditController.php
··· 1 - <?php 2 - 3 - /** 4 - * @group pholio 5 - */ 6 - final class PholioInlineEditController extends PholioController { 7 - 8 - private $id; 9 - private $operation; 10 - 11 - public function getOperation() { 12 - return $this->operation; 13 - } 14 - 15 - public function willProcessRequest(array $data) { 16 - $this->id = $data['id']; 17 - } 18 - 19 - public function processRequest() { 20 - $request = $this->getRequest(); 21 - $user = $request->getUser(); 22 - 23 - $this->operation = $request->getBool('op'); 24 - 25 - $inline_comment = id(new PholioTransactionComment())->loadOneWhere( 26 - 'id = %d AND authorphid = %s AND transactionphid IS NULL', 27 - $this->id, 28 - $user->getPHID()); 29 - 30 - if ($inline_comment == null) { 31 - return new Aphront404Response(); 32 - } 33 - 34 - switch ($this->getOperation()) { 35 - case 'update': 36 - $new_content = $request->getStr('content'); 37 - 38 - if (strlen(trim($new_content)) == 0) { 39 - return id(new AphrontAjaxResponse()) 40 - ->setContent(array('success' => false)) 41 - ->setError(pht('Empty comment')); 42 - } 43 - 44 - $inline_comment->setContent($request->getStr('content')); 45 - $inline_comment->save(); 46 - 47 - return id(new AphrontAjaxResponse()) 48 - ->setContent(array('success' => true)); 49 - 50 - default: 51 - $dialog = new PholioInlineCommentEditView(); 52 - $dialog->setInlineComment($inline_comment); 53 - 54 - $dialog->setUser($user); 55 - $dialog->setSubmitURI($request->getRequestURI()); 56 - 57 - $dialog->setTitle(pht('Edit inline comment')); 58 - 59 - $dialog->addHiddenInput('id', $this->id); 60 - $dialog->addHiddenInput('op', 'edit'); 61 - 62 - $dialog->appendChild( 63 - $this->renderTextArea($inline_comment->getContent())); 64 - 65 - return id(new AphrontAjaxResponse())->setContent($dialog->render()); 66 - } 67 - 68 - } 69 - 70 - private function renderTextArea($text) { 71 - return javelin_tag( 72 - 'textarea', 73 - array( 74 - 'class' => 'pholio-inline-comment-dialog-textarea', 75 - 'name' => 'text', 76 - ), 77 - $text); 78 - } 79 - 80 - 81 - 82 - }
+40
src/applications/pholio/controller/PholioInlineListController.php
··· 1 + <?php 2 + 3 + final class PholioInlineListController extends PholioController { 4 + 5 + private $id; 6 + 7 + public function willProcessRequest(array $data) { 8 + $this->id = $data['id']; 9 + } 10 + 11 + public function processRequest() { 12 + $request = $this->getRequest(); 13 + $user = $request->getUser(); 14 + 15 + $image = id(new PholioImageQuery()) 16 + ->setViewer($user) 17 + ->withIDs(array($this->id)) 18 + ->executeOne(); 19 + if (!$image) { 20 + return new Aphront404Response(); 21 + } 22 + 23 + $inline_comments = id(new PholioTransactionComment())->loadAllWhere( 24 + 'imageid = %d AND (transactionphid IS NOT NULL 25 + OR (authorphid = %s AND transactionphid IS NULL))', 26 + $this->id, 27 + $user->getPHID()); 28 + 29 + $author_phids = mpull($inline_comments, 'getAuthorPHID'); 30 + $authors = $this->loadViewerHandles($author_phids); 31 + 32 + $inlines = array(); 33 + foreach ($inline_comments as $inline_comment) { 34 + $inlines[] = $inline_comment->toDictionary(); 35 + } 36 + 37 + return id(new AphrontAjaxResponse())->setContent($inlines); 38 + } 39 + 40 + }
-94
src/applications/pholio/controller/PholioInlineSaveController.php
··· 1 - <?php 2 - 3 - /** 4 - * @group pholio 5 - */ 6 - final class PholioInlineSaveController extends PholioController { 7 - 8 - private $operation; 9 - 10 - public function getOperation() { 11 - return $this->operation; 12 - } 13 - 14 - public function processRequest() { 15 - $request = $this->getRequest(); 16 - $user = $request->getUser(); 17 - 18 - $mock = id(new PholioMockQuery()) 19 - ->setViewer($user) 20 - ->withIDs(array($request->getInt('mockID'))) 21 - ->executeOne(); 22 - 23 - if (!$mock) { 24 - return new Aphront404Response(); 25 - } 26 - 27 - $this->operation = $request->getStr('op'); 28 - 29 - if ($this->getOperation() == 'save') { 30 - $new_content = $request->getStr('text'); 31 - 32 - if (!strlen($new_content)) { 33 - throw new Exception('Content must not be empty.'); 34 - } 35 - 36 - $draft = id(new PholioTransactionComment()); 37 - $draft->setImageID($request->getInt('imageID')); 38 - $draft->setX($request->getInt('startX')); 39 - $draft->setY($request->getInt('startY')); 40 - 41 - $draft->setCommentVersion(1); 42 - $draft->setAuthorPHID($user->getPHID()); 43 - $draft->setEditPolicy($user->getPHID()); 44 - $draft->setViewPolicy(PhabricatorPolicies::POLICY_PUBLIC); 45 - $draft->setContentSourceFromRequest($request); 46 - 47 - $draft->setWidth($request->getInt('endX') - $request->getInt('startX')); 48 - $draft->setHeight($request->getInt('endY') - $request->getInt('startY')); 49 - 50 - $draft->setContent($new_content); 51 - 52 - $draft->save(); 53 - 54 - $handle = head($this->loadViewerHandles(array($user->getPHID()))); 55 - 56 - $inline_view = id(new PholioInlineCommentView()) 57 - ->setInlineComment($draft) 58 - ->setEngine(new PhabricatorMarkupEngine()) 59 - ->setUser($user) 60 - ->setHandle($handle); 61 - 62 - return id(new AphrontAjaxResponse()) 63 - ->setContent( 64 - $draft->toDictionary() + array( 65 - 'contentHTML' => $inline_view->render(), 66 - )); 67 - } else { 68 - $dialog = new PholioInlineCommentSaveView(); 69 - 70 - $dialog->setUser($user); 71 - $dialog->setSubmitURI($request->getRequestURI()); 72 - 73 - $dialog->setTitle(pht('Add Inline Comment')); 74 - 75 - $dialog->addHiddenInput('op', 'save'); 76 - 77 - $dialog->appendChild($this->renderTextArea('')); 78 - 79 - return id(new AphrontAjaxResponse())->setContent($dialog->render()); 80 - } 81 - 82 - } 83 - 84 - private function renderTextArea($text) { 85 - return javelin_tag( 86 - 'textarea', 87 - array( 88 - 'class' => 'pholio-inline-comment-dialog-textarea', 89 - 'name' => 'text', 90 - ), 91 - $text); 92 - } 93 - 94 - }
-34
src/applications/pholio/controller/PholioInlineViewController.php
··· 1 - <?php 2 - 3 - /** 4 - * @group pholio 5 - */ 6 - final class PholioInlineViewController extends PholioController { 7 - 8 - private $id; 9 - 10 - public function willProcessRequest(array $data) { 11 - $this->id = $data['id']; 12 - } 13 - 14 - public function processRequest() { 15 - $request = $this->getRequest(); 16 - $user = $request->getUser(); 17 - 18 - $inline_comment = id(new PholioTransactionComment())->load($this->id); 19 - $handle = head($this->loadViewerHandles( 20 - array($inline_comment->getAuthorPHID()))); 21 - 22 - $inline_view = id(new PholioInlineCommentView()) 23 - ->setUser($user) 24 - ->setHandle($handle) 25 - ->setInlineComment($inline_comment) 26 - ->setEngine(new PhabricatorMarkupEngine()); 27 - 28 - return id(new AphrontAjaxResponse())->setContent( 29 - $inline_comment->toDictionary() + array( 30 - 'contentHTML' => $inline_view->render(), 31 - )); 32 - } 33 - 34 - }
-3
src/applications/pholio/query/PholioImageQuery.php
··· 1 1 <?php 2 2 3 - /** 4 - * @group pholio 5 - */ 6 3 final class PholioImageQuery 7 4 extends PhabricatorCursorPagedPolicyAwareQuery { 8 5
+1 -1
src/applications/pholio/storage/PholioTransactionComment.php
··· 21 21 return array( 22 22 'id' => $this->getID(), 23 23 'phid' => $this->getPHID(), 24 - 'transactionphid' => $this->getTransactionPHID(), 24 + 'transactionPHID' => $this->getTransactionPHID(), 25 25 'x' => $this->getX(), 26 26 'y' => $this->getY(), 27 27 'width' => $this->getWidth(),
-140
src/applications/pholio/view/PholioInlineCommentEditView.php
··· 1 - <?php 2 - 3 - /** 4 - * @group pholio 5 - */ 6 - final class PholioInlineCommentEditView extends AphrontView { 7 - 8 - private $inputs = array(); 9 - private $uri; 10 - private $title; 11 - 12 - private $inlineComment; 13 - 14 - public function addHiddenInput($key, $value) { 15 - $this->inputs[] = array($key, $value); 16 - return $this; 17 - } 18 - 19 - public function setSubmitURI($uri) { 20 - $this->uri = $uri; 21 - return $this; 22 - } 23 - 24 - public function setTitle($title) { 25 - $this->title = $title; 26 - return $this; 27 - } 28 - 29 - public function setInlineComment($inline_comment) { 30 - $this->inlineComment = $inline_comment; 31 - return $this; 32 - } 33 - 34 - public function render() { 35 - if (!$this->uri) { 36 - throw new Exception('Call setSubmitURI() before render()!'); 37 - } 38 - if (!$this->user) { 39 - throw new Exception('Call setUser() before render()!'); 40 - } 41 - 42 - $content = phabricator_form( 43 - $this->user, 44 - array( 45 - 'action' => $this->uri, 46 - 'method' => 'POST', 47 - 'sigil' => 'inline-edit-form', 48 - ), 49 - array( 50 - $this->renderInputs(), 51 - $this->renderBody(), 52 - )); 53 - 54 - return $content; 55 - } 56 - 57 - private function renderInputs() { 58 - $out = array(); 59 - foreach ($this->inputs as $input) { 60 - list($name, $value) = $input; 61 - $out[] = phutil_tag( 62 - 'input', 63 - array( 64 - 'type' => 'hidden', 65 - 'name' => $name, 66 - 'value' => $value, 67 - )); 68 - } 69 - return $out; 70 - } 71 - 72 - private function renderBody() { 73 - $buttons = array(); 74 - 75 - $buttons[] = javelin_tag( 76 - 'button', 77 - array( 78 - 'sigil' => 'inline-edit-submit', 79 - 'meta' => array( 80 - 'id' => $this->inlineComment->getID(), 81 - 'phid' => $this->inlineComment->getPHID() 82 - ) 83 - ), 84 - pht('Ready')); 85 - $buttons[] = javelin_tag( 86 - 'button', 87 - array( 88 - 'sigil' => 'inline-edit-cancel', 89 - 'meta' => array( 90 - 'id' => $this->inlineComment->getID() 91 - ), 92 - 'class' => 'grey', 93 - ), 94 - pht('Cancel')); 95 - 96 - $formatting = phutil_tag( 97 - 'a', 98 - array( 99 - 'href' => PhabricatorEnv::getDoclink('Remarkup Reference'), 100 - 'tabindex' => '-1', 101 - 'target' => '_blank', 102 - ), 103 - pht('Formatting Reference')); 104 - 105 - $title = phutil_tag( 106 - 'div', 107 - array( 108 - 'class' => 'pholio-inline-comment-dialog-title', 109 - ), 110 - $this->title); 111 - 112 - $body = phutil_tag( 113 - 'div', 114 - array(), 115 - $this->renderChildren()); 116 - 117 - $edit = phutil_tag( 118 - 'edit', 119 - array( 120 - 'class' => 'pholio-inline-comment-dialog-buttons', 121 - ), 122 - array( 123 - $formatting, 124 - $buttons, 125 - phutil_tag('div', array('style' => 'clear: both'), ''), 126 - )); 127 - 128 - return javelin_tag( 129 - 'div', 130 - array( 131 - 'class' => 'pholio-inline-comment-dialog', 132 - ), 133 - array( 134 - $title, 135 - $body, 136 - $edit, 137 - )); 138 - } 139 - 140 - }
-127
src/applications/pholio/view/PholioInlineCommentSaveView.php
··· 1 - <?php 2 - 3 - /** 4 - * @group pholio 5 - */ 6 - final class PholioInlineCommentSaveView extends AphrontView { 7 - 8 - private $inputs = array(); 9 - private $uri; 10 - private $title; 11 - 12 - public function addHiddenInput($key, $value) { 13 - $this->inputs[] = array($key, $value); 14 - return $this; 15 - } 16 - 17 - public function setSubmitURI($uri) { 18 - $this->uri = $uri; 19 - return $this; 20 - } 21 - 22 - public function setTitle($title) { 23 - $this->title = $title; 24 - return $this; 25 - } 26 - 27 - public function render() { 28 - if (!$this->uri) { 29 - throw new Exception('Call setSubmitURI() before render()!'); 30 - } 31 - if (!$this->user) { 32 - throw new Exception('Call setUser() before render()!'); 33 - } 34 - 35 - $content = phabricator_form( 36 - $this->user, 37 - array( 38 - 'action' => $this->uri, 39 - 'method' => 'POST', 40 - 'sigil' => 'inline-save-form', 41 - 'class' => 'pholio-new-inline-comment', 42 - 'id' => 'pholio-new-inline-comment-dialog' 43 - ), 44 - array( 45 - $this->renderInputs(), 46 - $this->renderBody(), 47 - )); 48 - 49 - return $content; 50 - } 51 - 52 - private function renderInputs() { 53 - $out = array(); 54 - foreach ($this->inputs as $input) { 55 - list($name, $value) = $input; 56 - $out[] = phutil_tag( 57 - 'input', 58 - array( 59 - 'type' => 'hidden', 60 - 'name' => $name, 61 - 'value' => $value, 62 - )); 63 - } 64 - return $out; 65 - } 66 - 67 - private function renderBody() { 68 - $buttons = array(); 69 - 70 - $buttons[] = javelin_tag( 71 - 'button', 72 - array( 73 - 'sigil' => 'inline-save-submit', 74 - ), 75 - pht('Done')); 76 - $buttons[] = javelin_tag( 77 - 'button', 78 - array( 79 - 'sigil' => 'inline-save-cancel', 80 - 'class' => 'grey', 81 - ), 82 - pht('Cancel')); 83 - 84 - $formatting = phutil_tag( 85 - 'a', 86 - array( 87 - 'href' => PhabricatorEnv::getDoclink('Remarkup Reference'), 88 - 'tabindex' => '-1', 89 - 'target' => '_blank', 90 - ), 91 - pht('Formatting Reference')); 92 - 93 - $title = phutil_tag( 94 - 'div', 95 - array( 96 - 'class' => 'pholio-inline-comment-dialog-title', 97 - ), 98 - $this->title); 99 - 100 - $body = phutil_tag( 101 - 'div', 102 - array(), 103 - $this->renderChildren()); 104 - 105 - $edit = phutil_tag( 106 - 'edit', 107 - array( 108 - 'class' => 'pholio-inline-comment-dialog-buttons', 109 - ), 110 - array( 111 - $formatting, 112 - $buttons, 113 - phutil_tag('div', array('style' => 'clear: both'), ''), 114 - )); 115 - 116 - return javelin_tag( 117 - 'div', 118 - array( 119 - ), 120 - array( 121 - $title, 122 - $body, 123 - $edit, 124 - )); 125 - } 126 - 127 - }
-136
src/applications/pholio/view/PholioInlineCommentView.php
··· 1 - <?php 2 - 3 - /** 4 - * @group pholio 5 - */ 6 - final class PholioInlineCommentView extends AphrontView { 7 - 8 - private $engine; 9 - private $handle; 10 - private $inlineComment; 11 - 12 - public function setEngine(PhabricatorMarkupEngine $engine) { 13 - $this->engine = $engine; 14 - return $this; 15 - } 16 - 17 - public function setHandle(PhabricatorObjectHandle $handle) { 18 - $this->handle = $handle; 19 - return $this; 20 - } 21 - 22 - public function setInlineComment(PholioTransactionComment $inline_comment) { 23 - if ($inline_comment->getImageID() === null) { 24 - throw new Exception('Comment provided is not inline comment'); 25 - } 26 - 27 - $this->inlineComment = $inline_comment; 28 - return $this; 29 - } 30 - 31 - public function render() { 32 - if (!$this->inlineComment) { 33 - throw new Exception('Call setInlineComment() before render()!'); 34 - } 35 - if ($this->user === null) { 36 - throw new Exception('Call setUser() before render()!'); 37 - } 38 - if ($this->engine === null) { 39 - throw new Exception('Call setEngine() before render()!'); 40 - } 41 - if ($this->handle === null) { 42 - throw new Exception('Call setHandle() before render()!'); 43 - } 44 - 45 - $actions = null; 46 - $inline = $this->inlineComment; 47 - $phid = $inline->getPHID(); 48 - $id = $inline->getID(); 49 - $user = $this->user; 50 - 51 - $is_draft = ($inline->getTransactionPHID() === null); 52 - $can_edit = PhabricatorPolicyFilter::hasCapability( 53 - $user, 54 - $inline, 55 - PhabricatorPolicyCapability::CAN_EDIT); 56 - 57 - if ($is_draft && $can_edit) { 58 - $draft = phutil_tag( 59 - 'span', 60 - array( 61 - 'class' => 'pholio-inline-status', 62 - ), 63 - pht('Not Submitted Yet')); 64 - 65 - $edit_action = javelin_tag( 66 - 'a', 67 - array( 68 - 'href' => '/pholio/inline/edit/'.$id.'/', 69 - 'sigil' => 'inline-edit', 70 - 'meta' => array( 71 - 'phid' => $phid, 72 - 'id' => $id, 73 - ) 74 - ), 75 - pht('Edit')); 76 - 77 - $delete_action = javelin_tag( 78 - 'a', 79 - array( 80 - 'href' => '/pholio/inline/delete/'.$id.'/', 81 - 'sigil' => 'inline-delete', 82 - 'meta' => array( 83 - 'phid' => $phid, 84 - 'id' => $id, 85 - ) 86 - ), 87 - pht('Delete')); 88 - 89 - $actions = phutil_tag( 90 - 'span', 91 - array( 92 - 'class' => 'pholio-inline-head-links' 93 - ), 94 - phutil_implode_html( 95 - " \xC2\xB7 ", 96 - array($draft, $edit_action, $delete_action))); 97 - } 98 - 99 - $comment_header = phutil_tag( 100 - 'div', 101 - array( 102 - 'class' => 'pholio-inline-comment-header' 103 - ), 104 - array($this->handle->getName(), $actions)); 105 - 106 - 107 - $comment = $this->engine->renderOneObject( 108 - $inline, 109 - PholioTransactionComment::MARKUP_FIELD_COMMENT, 110 - $this->user); 111 - 112 - $comment_body = phutil_tag( 113 - 'div', 114 - array(), 115 - $comment); 116 - 117 - $classes = array(); 118 - $classes[] = 'pholio-inline-comment'; 119 - 120 - if ($is_draft) { 121 - $classes[] = 'pholio-inline-comment-draft'; 122 - } 123 - 124 - return javelin_tag( 125 - 'div', 126 - array( 127 - 'id' => "{$phid}_comment", 128 - 'class' => implode(' ', $classes), 129 - 'sigil' => 'inline_comment', 130 - 'meta' => array( 131 - 'phid' => $phid, 132 - ) 133 - ), 134 - array($comment_header, $comment_body)); 135 - } 136 - }
+3 -3
webroot/rsrc/css/application/pholio/pholio.css
··· 148 148 } 149 149 150 150 .pholio-mock-reticle-selection { 151 - background: #ffffff; 152 - opacity: 0.40; 151 + background-color: rgba(255, 255, 255, 0.50); 153 152 border: 1px dashed #000; 154 153 } 155 154 ··· 165 164 166 165 .pholio-mock-reticle-draft:hover, 167 166 .pholio-mock-reticle-final:hover { 168 - border: 1px solid rgba(255, 255, 255, 0.50); 167 + background-color: rgba(255, 255, 255, 0.50); 168 + cursor: pointer; 169 169 } 170 170 171 171
+64 -212
webroot/rsrc/js/application/pholio/behavior-pholio-mock-view.js
··· 34 34 var loading = false; 35 35 var stageElement = JX.$(config.panelID); 36 36 var viewElement = JX.$(config.viewportID); 37 - var gutterElement = JX.$('mock-inline-comments'); 38 37 var reticles = []; 39 - var cards = []; 40 - var inline_phid_map = {}; 41 38 42 39 function begin_load() { 43 40 if (loading) { ··· 60 57 JX.DOM.alterClass(stageElement, 'pholio-image-loading', loading); 61 58 } 62 59 63 - function add_inline_node(node, phid) { 64 - inline_phid_map[phid] = (inline_phid_map[phid] || []); 65 - inline_phid_map[phid].push(node); 66 - } 67 - 68 - function add_reticle(reticle, phid) { 69 - mark_ref(reticle, phid); 70 - 60 + function add_reticle(reticle, id) { 61 + mark_ref(reticle, id); 71 62 reticles.push(reticle); 72 - add_inline_node(reticle, phid); 73 - 74 63 viewElement.appendChild(reticle); 75 64 } 76 65 ··· 78 67 var ii; 79 68 for (ii = 0; ii < reticles.length; ii++) { 80 69 JX.DOM.remove(reticles[ii]); 81 - } 82 - for (ii = 0; ii < cards.length; ii++) { 83 - JX.DOM.remove(cards[ii]); 84 70 } 85 71 reticles = []; 86 - cards = []; 87 - inline_phid_map = {}; 88 72 } 89 73 90 - function highlight_inline(phid, show) { 91 - var nodes = inline_phid_map[phid] || []; 92 - var cls = 'pholio-mock-inline-comment-highlight'; 93 - for (var ii = 0; ii < nodes.length; ii++) { 94 - JX.DOM.alterClass(nodes[ii], cls, show); 95 - } 96 - } 97 - 98 - function remove_inline(phid) { 99 - var nodes = inline_phid_map[phid] || []; 100 - for (var ii = 0; ii < nodes.length; ii++) { 101 - JX.DOM.remove(nodes[ii]); 102 - } 103 - delete inline_phid_map[phid]; 104 - } 105 - 106 - function mark_ref(node, phid) { 74 + function mark_ref(node, id) { 107 75 JX.Stratcom.addSigil(node, 'pholio-inline-ref'); 108 - JX.Stratcom.addData(node, {phid: phid}); 109 - } 110 - 111 - function add_card(card, phid) { 112 - mark_ref(card, phid); 113 - 114 - cards.push(card); 115 - add_inline_node(card, phid); 116 - 117 - gutterElement.appendChild(card); 76 + JX.Stratcom.addData(node, {inlineID: id}); 118 77 } 119 78 120 79 return { 121 80 beginLoad: begin_load, 122 81 endLoad: end_load, 123 82 addReticle: add_reticle, 124 - clearStage: clear_stage, 125 - highlightInline: highlight_inline, 126 - removeInline: remove_inline, 127 - addCard: add_card 83 + clearStage: clear_stage 128 84 }; 129 85 })(); 130 86 131 87 JX.enableDispatch(document.body, 'mouseenter'); 132 88 JX.enableDispatch(document.body, 'mouseleave'); 133 89 134 - JX.Stratcom.listen('mouseenter', 'mock-panel', function(e) { 135 - JX.DOM.alterClass(e.getNode('mock-panel'), 'mock-has-cursor', true); 136 - }); 90 + JX.Stratcom.listen( 91 + ['mouseenter', 'mouseover'], 92 + 'mock-panel', 93 + function(e) { 94 + JX.DOM.alterClass(e.getNode('mock-panel'), 'mock-has-cursor', true); 95 + }); 137 96 138 97 JX.Stratcom.listen('mouseleave', 'mock-panel', function(e) { 139 98 var node = e.getNode('mock-panel'); ··· 248 207 } 249 208 250 209 load_inline_comments(); 251 - 252 210 if (image_id != config.selectedID) { 253 211 JX.History.replace(active_image.pageURI); 254 212 } ··· 280 238 return; 281 239 } 282 240 283 - if (drag_begin) { 241 + if (JX.Stratcom.pass()) { 242 + return; 243 + } 244 + 245 + if (is_dragging) { 284 246 return; 285 247 } 286 248 ··· 304 266 }); 305 267 306 268 JX.Stratcom.listen( 307 - ['mouseover', 'mouseout'], 269 + 'mousedown', 308 270 'pholio-inline-ref', 309 271 function(e) { 310 - var phid = e.getNodeData('pholio-inline-ref').phid; 311 - var show = (e.getType() == 'mouseover'); 312 - stage.highlightInline(phid, show); 272 + e.kill(); 273 + 274 + var id = e.getNodeData('pholio-inline-ref').inlineID; 275 + 276 + var active_id = active_image.id; 277 + var handler = function(r) { 278 + var inlines = inline_comments[active_id]; 279 + 280 + for (var ii = 0; ii < inlines.length; ii++) { 281 + if (inlines[ii].id == id) { 282 + if (r.id) { 283 + inlines[ii] = r; 284 + } else { 285 + inlines.splice(ii, 1); 286 + } 287 + break; 288 + } 289 + } 290 + 291 + redraw_inlines(active_id); 292 + JX.DOM.invoke(JX.$(config.commentFormID), 'shouldRefresh'); 293 + }; 294 + 295 + new JX.Workflow('/pholio/inline/' + id + '/') 296 + .setHandler(handler) 297 + .start(); 313 298 }); 314 299 315 300 JX.Stratcom.listen( ··· 331 316 332 317 resize_selection(16); 333 318 334 - var data = {mockID: config.mockID}; 319 + var data = { 320 + mockID: config.mockID, 321 + imageID: active_image.id, 322 + startX: Math.min(drag_begin.x, drag_end.x), 323 + startY: Math.min(drag_begin.y, drag_end.y), 324 + endX: Math.max(drag_begin.x, drag_end.x), 325 + endY: Math.max(drag_begin.y, drag_end.y) 326 + }; 327 + 335 328 var handler = function(r) { 336 - var dialog = JX.$H(r).getFragment().firstChild; 337 - JX.DOM.appendContent(viewport, dialog); 338 - 339 - var x = Math.min(drag_begin.x * scale, drag_end.x * scale); 340 - var y = Math.max(drag_begin.y * scale, drag_end.y * scale) + 4; 341 - JX.$V(x, y).setPos(dialog); 329 + if (!inline_comments[active_image.id]) { 330 + inline_comments[active_image.id] = []; 331 + } 332 + inline_comments[active_image.id].push(r); 342 333 343 - JX.DOM.focus(JX.DOM.find(dialog, 'textarea')); 334 + redraw_inlines(active_image.id); 335 + JX.DOM.invoke(JX.$(config.commentFormID), 'shouldRefresh'); 344 336 }; 345 337 346 - new JX.Workflow('/pholio/inline/save/', data) 338 + clear_selection(); 339 + 340 + new JX.Workflow('/pholio/inline/', data) 347 341 .setHandler(handler) 348 342 .start(); 349 343 }); ··· 413 407 414 408 for (var ii = 0; ii < inlines.length; ii++) { 415 409 var inline = inlines[ii]; 416 - var card = JX.$H(inline.contentHTML).getFragment().firstChild; 417 - 418 - stage.addCard(card, inline.phid); 419 410 420 411 if (!active_image.tag) { 421 412 // The image itself hasn't loaded yet, so we can't draw the inline ··· 424 415 } 425 416 426 417 var classes = []; 427 - if (!inline.transactionphid) { 418 + if (!inline.transactionPHID) { 428 419 classes.push('pholio-mock-reticle-draft'); 429 420 } else { 430 421 classes.push('pholio-mock-reticle-final'); 431 422 } 432 423 433 424 var inline_selection = render_reticle(classes); 434 - stage.addReticle(inline_selection, inline.phid); 425 + stage.addReticle(inline_selection, inline.id); 435 426 position_inline_rectangle(inline, inline_selection); 436 427 } 437 428 } ··· 496 487 497 488 function load_inline_comments() { 498 489 var id = active_image.id; 499 - var inline_comments_uri = "/pholio/inline/" + id + "/"; 490 + var inline_comments_uri = '/pholio/inline/list/' + id + '/'; 500 491 501 492 new JX.Request(inline_comments_uri, function(r) { 502 493 inline_comments[id] = r; 503 494 redraw_inlines(id); 504 495 }).send(); 505 - } 506 - 507 - JX.Stratcom.listen( 508 - 'click', 509 - 'inline-delete', 510 - function(e) { 511 - var data = e.getNodeData('inline-delete'); 512 - e.kill(); 513 - interrupt_typing(); 514 - 515 - stage.removeInline(data.phid); 516 - 517 - var deleteURI = '/pholio/inline/delete/' + data.id + '/'; 518 - var del = new JX.Request(deleteURI, function(r) { 519 - 520 - }); 521 - del.send(); 522 - 523 - }); 524 - 525 - JX.Stratcom.listen( 526 - 'click', 527 - 'inline-edit', 528 - function(e) { 529 - var data = e.getNodeData('inline-edit'); 530 - e.kill(); 531 - 532 - interrupt_typing(); 533 - 534 - var editURI = "/pholio/inline/edit/" + data.id + '/'; 535 - 536 - var edit_dialog = new JX.Request(editURI, function(r) { 537 - var dialog = JX.$N( 538 - 'div', 539 - { 540 - className: 'pholio-edit-inline-popup' 541 - }, 542 - JX.$H(r)); 543 - 544 - JX.DOM.setContent(JX.$(data.phid + '_comment'), dialog); 545 - }); 546 - 547 - edit_dialog.send(); 548 - }); 549 - 550 - JX.Stratcom.listen( 551 - 'click', 552 - 'inline-edit-cancel', 553 - function(e) { 554 - var data = e.getNodeData('inline-edit-cancel'); 555 - e.kill(); 556 - load_inline_comment(data.id); 557 - }); 558 - 559 - JX.Stratcom.listen( 560 - 'click', 561 - 'inline-edit-submit', 562 - function(e) { 563 - var data = e.getNodeData('inline-edit-submit'); 564 - var editURI = "/pholio/inline/edit/" + data.id + '/'; 565 - e.kill(); 566 - 567 - var edit = new JX.Request(editURI, function(r) { 568 - load_inline_comment(data.id); 569 - JX.DOM.invoke(JX.$(config.commentFormID), 'shouldRefresh'); 570 - }); 571 - edit.addData({ 572 - op: 'update', 573 - content: JX.DOM.find(JX.$(data.phid + '_comment'), 'textarea').value 574 - }); 575 - edit.send(); 576 - }); 577 - 578 - JX.Stratcom.listen( 579 - 'click', 580 - 'inline-save-cancel', 581 - function(e) { 582 - e.kill(); 583 - interrupt_typing(); 584 - } 585 - ); 586 - 587 - JX.Stratcom.listen( 588 - 'click', 589 - 'inline-save-submit', 590 - function(e) { 591 - e.kill(); 592 - 593 - var form = JX.$('pholio-new-inline-comment-dialog'); 594 - var text = JX.DOM.find(form, 'textarea').value; 595 - if (!text.length) { 596 - interrupt_typing(); 597 - return; 598 - } 599 - 600 - var data = { 601 - mockID: config.mockID, 602 - imageID: active_image.id, 603 - startX: Math.min(drag_begin.x, drag_end.x), 604 - startY: Math.min(drag_begin.y, drag_end.y), 605 - endX: Math.max(drag_begin.x, drag_end.x), 606 - endY: Math.max(drag_begin.y, drag_end.y) 607 - }; 608 - 609 - var handler = function(r) { 610 - if (!inline_comments[active_image.id]) { 611 - inline_comments[active_image.id] = []; 612 - } 613 - inline_comments[active_image.id].push(r); 614 - 615 - interrupt_typing(); 616 - redraw_inlines(active_image.id); 617 - JX.DOM.invoke(JX.$(config.commentFormID), 'shouldRefresh'); 618 - }; 619 - 620 - JX.Workflow.newFromForm(form, data) 621 - .setHandler(handler) 622 - .start(); 623 - } 624 - ); 625 - 626 - function load_inline_comment(id) { 627 - var viewInlineURI = '/pholio/inline/view/' + id + '/'; 628 - var inline_comment = new JX.Request(viewInlineURI, function(r) { 629 - JX.DOM.replace(JX.$(r.phid + '_comment'), JX.$H(r.contentHTML)); 630 - }); 631 - inline_comment.send(); 632 - } 633 - 634 - function interrupt_typing() { 635 - clear_selection(); 636 - 637 - try { 638 - JX.DOM.remove(JX.$('pholio-new-inline-comment-dialog')); 639 - } catch (x) { 640 - // TODO: For now, ignore this. 641 - } 642 - 643 - drag_begin = null; 644 496 } 645 497 646 498 load_inline_comments();