diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 6abd53f857..9bf296a0b0 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -341,7 +341,7 @@ return array( 'rsrc/js/application/conpherence/behavior-menu.js' => 'd3782c93', 'rsrc/js/application/conpherence/behavior-pontificate.js' => '21ba5861', 'rsrc/js/application/conpherence/behavior-quicksand-blacklist.js' => '7927a7d3', - 'rsrc/js/application/conpherence/behavior-widget-pane.js' => '93568464', + 'rsrc/js/application/conpherence/behavior-widget-pane.js' => 'cafc59ab', 'rsrc/js/application/countdown/timer.js' => 'e4cc26b3', 'rsrc/js/application/daemon/behavior-bulk-job-reload.js' => 'edf8a145', 'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => '469c0d9e', @@ -548,7 +548,7 @@ return array( 'javelin-behavior-conpherence-drag-and-drop-photo' => 'cf86d16a', 'javelin-behavior-conpherence-menu' => 'd3782c93', 'javelin-behavior-conpherence-pontificate' => '21ba5861', - 'javelin-behavior-conpherence-widget-pane' => '93568464', + 'javelin-behavior-conpherence-widget-pane' => 'cafc59ab', 'javelin-behavior-countdown-timer' => 'e4cc26b3', 'javelin-behavior-dark-console' => 'f411b6ae', 'javelin-behavior-dashboard-async-panel' => '469c0d9e', @@ -1511,19 +1511,6 @@ return array( 'javelin-dom', 'javelin-stratcom', ), - 93568464 => array( - 'javelin-behavior', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-workflow', - 'javelin-util', - 'phabricator-notification', - 'javelin-behavior-device', - 'phuix-dropdown-menu', - 'phuix-action-list-view', - 'phuix-action-view', - 'conpherence-thread-manager', - ), '93d0c9e3' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1771,6 +1758,19 @@ return array( 'javelin-stratcom', 'phabricator-phtize', ), + 'cafc59ab' => array( + 'javelin-behavior', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-workflow', + 'javelin-util', + 'phabricator-notification', + 'javelin-behavior-device', + 'phuix-dropdown-menu', + 'phuix-action-list-view', + 'phuix-action-view', + 'conpherence-thread-manager', + ), 'ccf1cbf8' => array( 'javelin-install', 'javelin-dom', diff --git a/resources/sql/autopatches/20150619.conpherencerooms.1.sql b/resources/sql/autopatches/20150619.conpherencerooms.1.sql new file mode 100644 index 0000000000..c7c5c56053 --- /dev/null +++ b/resources/sql/autopatches/20150619.conpherencerooms.1.sql @@ -0,0 +1,6 @@ +UPDATE {$NAMESPACE}_conpherence.conpherence_thread + SET + viewPolicy = 'obj.conpherence.members', + editPolicy = 'obj.conpherence.members', + joinPolicy = 'obj.conpherence.members' + WHERE isRoom = 0; diff --git a/resources/sql/autopatches/20150619.conpherencerooms.2.sql b/resources/sql/autopatches/20150619.conpherencerooms.2.sql new file mode 100644 index 0000000000..e6c54a0921 --- /dev/null +++ b/resources/sql/autopatches/20150619.conpherencerooms.2.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_conpherence.conpherence_thread + DROP KEY `key_room`; diff --git a/resources/sql/autopatches/20150619.conpherencerooms.3.sql b/resources/sql/autopatches/20150619.conpherencerooms.3.sql new file mode 100644 index 0000000000..c4fb35b57c --- /dev/null +++ b/resources/sql/autopatches/20150619.conpherencerooms.3.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_conpherence.conpherence_thread + DROP COLUMN isRoom; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 250b4b07db..c2429d9f97 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -241,7 +241,6 @@ phutil_register_library_map(array( 'ConpherenceLayoutView' => 'applications/conpherence/view/ConpherenceLayoutView.php', 'ConpherenceListController' => 'applications/conpherence/controller/ConpherenceListController.php', 'ConpherenceMenuItemView' => 'applications/conpherence/view/ConpherenceMenuItemView.php', - 'ConpherenceNewController' => 'applications/conpherence/controller/ConpherenceNewController.php', 'ConpherenceNewRoomController' => 'applications/conpherence/controller/ConpherenceNewRoomController.php', 'ConpherenceNotificationPanelController' => 'applications/conpherence/controller/ConpherenceNotificationPanelController.php', 'ConpherenceParticipant' => 'applications/conpherence/storage/ConpherenceParticipant.php', @@ -266,7 +265,6 @@ phutil_register_library_map(array( 'ConpherenceThreadQuery' => 'applications/conpherence/query/ConpherenceThreadQuery.php', 'ConpherenceThreadRemarkupRule' => 'applications/conpherence/remarkup/ConpherenceThreadRemarkupRule.php', 'ConpherenceThreadSearchEngine' => 'applications/conpherence/query/ConpherenceThreadSearchEngine.php', - 'ConpherenceThreadTestCase' => 'applications/conpherence/__tests__/ConpherenceThreadTestCase.php', 'ConpherenceTransaction' => 'applications/conpherence/storage/ConpherenceTransaction.php', 'ConpherenceTransactionComment' => 'applications/conpherence/storage/ConpherenceTransactionComment.php', 'ConpherenceTransactionQuery' => 'applications/conpherence/query/ConpherenceTransactionQuery.php', @@ -3614,7 +3612,6 @@ phutil_register_library_map(array( 'ConpherenceLayoutView' => 'AphrontView', 'ConpherenceListController' => 'ConpherenceController', 'ConpherenceMenuItemView' => 'AphrontTagView', - 'ConpherenceNewController' => 'ConpherenceController', 'ConpherenceNewRoomController' => 'ConpherenceController', 'ConpherenceNotificationPanelController' => 'ConpherenceController', 'ConpherenceParticipant' => 'ConpherenceDAO', @@ -3645,7 +3642,6 @@ phutil_register_library_map(array( 'ConpherenceThreadQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'ConpherenceThreadRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'ConpherenceThreadSearchEngine' => 'PhabricatorApplicationSearchEngine', - 'ConpherenceThreadTestCase' => 'ConpherenceTestCase', 'ConpherenceTransaction' => 'PhabricatorApplicationTransaction', 'ConpherenceTransactionComment' => 'PhabricatorApplicationTransactionComment', 'ConpherenceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', diff --git a/src/applications/conpherence/__tests__/ConpherenceRoomTestCase.php b/src/applications/conpherence/__tests__/ConpherenceRoomTestCase.php index 4c66a48348..03dd615481 100644 --- a/src/applications/conpherence/__tests__/ConpherenceRoomTestCase.php +++ b/src/applications/conpherence/__tests__/ConpherenceRoomTestCase.php @@ -69,20 +69,6 @@ final class ConpherenceRoomTestCase extends ConpherenceTestCase { $participant_phids, $conpherence->getRecentParticipantPHIDs()); - // test policy error as another user tries to add - $caught = null; - try { - $this->addParticipants( - $friend_2, - $conpherence, - array($friend_3->getPHID())); - } catch (PhabricatorPolicyException $ex) { - $caught = $ex; - } - $this->assertTrue($caught instanceof PhabricatorPolicyException); - - // update edit policy so user has a chance - $this->changeEditPolicy($creator, $conpherence, 'users'); // test add by other participant, so recent participation should // meaningfully change $participant_phids = array( @@ -129,7 +115,6 @@ final class ConpherenceRoomTestCase extends ConpherenceTestCase { public function testAddMessageWithFileAttachments() { $creator = $this->generateNewTestUser(); $friend_1 = $this->generateNewTestUser(); - $join_via_add = $this->generateNewTestUser(); $participant_map = array( $creator->getPHID() => $creator, @@ -144,9 +129,6 @@ final class ConpherenceRoomTestCase extends ConpherenceTestCase { $xactions = $this->addMessageWithFile($user, $conpherence); $this->assertEqual(2, count($xactions)); } - - $xactions = $this->addMessageWithFile($join_via_add, $conpherence); - $this->assertEqual(2, count($xactions)); } private function createRoom( diff --git a/src/applications/conpherence/__tests__/ConpherenceThreadTestCase.php b/src/applications/conpherence/__tests__/ConpherenceThreadTestCase.php deleted file mode 100644 index 3013e998fa..0000000000 --- a/src/applications/conpherence/__tests__/ConpherenceThreadTestCase.php +++ /dev/null @@ -1,169 +0,0 @@ - true, - ); - } - - public function testOneUserThreadCreate() { - $creator = $this->generateNewTestUser(); - $participant_phids = array($creator->getPHID()); - - $conpherence = $this->createThread($creator, $participant_phids); - - $this->assertTrue((bool)$conpherence->getID()); - $this->assertEqual(1, count($conpherence->getParticipants())); - $this->assertEqual( - $participant_phids, - $conpherence->getRecentParticipantPHIDs()); - } - - public function testNUserThreadCreate() { - $creator = $this->generateNewTestUser(); - $friend_1 = $this->generateNewTestUser(); - $friend_2 = $this->generateNewTestUser(); - $friend_3 = $this->generateNewTestUser(); - - $participant_phids = array( - $creator->getPHID(), - $friend_1->getPHID(), - $friend_2->getPHID(), - $friend_3->getPHID(), - ); - - $conpherence = $this->createThread($creator, $participant_phids); - - $this->assertTrue((bool)$conpherence->getID()); - $this->assertEqual(4, count($conpherence->getParticipants())); - $this->assertEqual( - $participant_phids, - $conpherence->getRecentParticipantPHIDs()); - } - - public function testThreadParticipantAddition() { - $creator = $this->generateNewTestUser(); - $friend_1 = $this->generateNewTestUser(); - $friend_2 = $this->generateNewTestUser(); - $friend_3 = $this->generateNewTestUser(); - - $participant_phids = array( - $creator->getPHID(), - $friend_1->getPHID(), - ); - - $conpherence = $this->createThread($creator, $participant_phids); - - $this->assertTrue((bool)$conpherence->getID()); - $this->assertEqual(2, count($conpherence->getParticipants())); - $this->assertEqual( - $participant_phids, - $conpherence->getRecentParticipantPHIDs()); - - // test add by creator - $participant_phids[] = $friend_2->getPHID(); - $this->addParticipants($creator, $conpherence, array($friend_2->getPHID())); - $this->assertEqual( - $participant_phids, - $conpherence->getRecentParticipantPHIDs()); - - // test add by other participant, so recent participation should - // meaningfully change - $participant_phids = array( - $friend_2->getPHID(), // actor - $creator->getPHID(), // last actor - $friend_1->getPHID(), - $friend_3->getPHID(), // new addition - ); - $this->addParticipants( - $friend_2, - $conpherence, - array($friend_3->getPHID())); - $this->assertEqual( - $participant_phids, - $conpherence->getRecentParticipantPHIDs()); - } - - public function testThreadParticipantDeletion() { - $creator = $this->generateNewTestUser(); - $friend_1 = $this->generateNewTestUser(); - $friend_2 = $this->generateNewTestUser(); - $friend_3 = $this->generateNewTestUser(); - - $participant_map = array( - $creator->getPHID() => $creator, - $friend_1->getPHID() => $friend_1, - $friend_2->getPHID() => $friend_2, - $friend_3->getPHID() => $friend_3, - ); - - $conpherence = $this->createThread( - $creator, - array_keys($participant_map)); - - foreach ($participant_map as $phid => $user) { - $this->removeParticipants($user, $conpherence, array($phid)); - unset($participant_map[$phid]); - $this->assertEqual( - count($participant_map), - count($conpherence->getParticipants())); - } - } - - public function testAddMessageWithFileAttachments() { - $creator = $this->generateNewTestUser(); - $friend_1 = $this->generateNewTestUser(); - $policy_exception_user = $this->generateNewTestUser(); - - $participant_map = array( - $creator->getPHID() => $creator, - $friend_1->getPHID() => $friend_1, - ); - - $conpherence = $this->createThread( - $creator, - array_keys($participant_map)); - - foreach ($participant_map as $phid => $user) { - $xactions = $this->addMessageWithFile($user, $conpherence); - $this->assertEqual(2, count($xactions), pht('hi')); - } - - $caught = null; - try { - $xactions = $this->addMessageWithFile( - $policy_exception_user, - $conpherence); - } catch (PhabricatorPolicyException $ex) { - $caught = $ex; - } - $this->assertTrue( - $caught instanceof PhabricatorPolicyException, - pht( - 'User not participating in thread should get policy exception '. - 'trying to add message.')); - $this->assertTrue( - $conpherence->establishConnection('w')->isReadLocking(), - pht( - 'Conpherence object should still be read locked from policy '. - 'exception.')); - $conpherence->endReadLocking(); - $conpherence->killTransaction(); - } - - private function createThread( - PhabricatorUser $creator, - array $participant_phids) { - - list($errors, $conpherence) = ConpherenceEditor::createThread( - $creator, - $participant_phids, - pht('Test'), - pht('Test'), - PhabricatorContentSource::newConsoleSource()); - return $conpherence; - } - -} diff --git a/src/applications/conpherence/application/PhabricatorConpherenceApplication.php b/src/applications/conpherence/application/PhabricatorConpherenceApplication.php index 5d36022a04..852daa8bee 100644 --- a/src/applications/conpherence/application/PhabricatorConpherenceApplication.php +++ b/src/applications/conpherence/application/PhabricatorConpherenceApplication.php @@ -11,7 +11,7 @@ final class PhabricatorConpherenceApplication extends PhabricatorApplication { } public function getShortDescription() { - return pht('Send Messages'); + return pht('Chat with Others'); } public function getFontIcon() { @@ -44,8 +44,7 @@ final class PhabricatorConpherenceApplication extends PhabricatorApplication { '(?P[1-9]\d*)/(?P[1-9]\d*)/' => 'ConpherenceViewController', 'columnview/' => 'ConpherenceColumnViewController', - 'new/' => 'ConpherenceNewController', - 'room/new/' => 'ConpherenceNewRoomController', + 'new/' => 'ConpherenceNewRoomController', 'search/(?:query/(?P[^/]+)/)?' => 'ConpherenceRoomListController', 'panel/' => 'ConpherenceNotificationPanelController', @@ -59,7 +58,7 @@ final class PhabricatorConpherenceApplication extends PhabricatorApplication { $items = array(); $item = id(new PHUIListItemView()) - ->setName(pht('Conpherence Thread')) + ->setName(pht('Conpherence Room')) ->setIcon('fa-comments') ->setWorkflow(true) ->setHref($this->getBaseURI().'new/'); diff --git a/src/applications/conpherence/conduit/ConpherenceQueryTransactionConduitAPIMethod.php b/src/applications/conpherence/conduit/ConpherenceQueryTransactionConduitAPIMethod.php index e014dc742a..7de3b0678d 100644 --- a/src/applications/conpherence/conduit/ConpherenceQueryTransactionConduitAPIMethod.php +++ b/src/applications/conpherence/conduit/ConpherenceQueryTransactionConduitAPIMethod.php @@ -10,15 +10,15 @@ final class ConpherenceQueryTransactionConduitAPIMethod public function getMethodDescription() { return pht( 'Query for transactions for the logged in user within a specific '. - 'Conpherence thread. You can specify the thread by ID or PHID. '. + 'Conpherence room. You can specify the room by ID or PHID. '. 'Otherwise, specify limit and offset to query the most recent '. - 'transactions within the Conpherence for the logged in user.'); + 'transactions within the Conpherence room for the logged in user.'); } protected function defineParamTypes() { return array( - 'threadID' => 'optional int', - 'threadPHID' => 'optional phid', + 'roomID' => 'optional int', + 'roomPHID' => 'optional phid', 'limit' => 'optional int', 'offset' => 'optional int', ); @@ -30,28 +30,28 @@ final class ConpherenceQueryTransactionConduitAPIMethod protected function defineErrorTypes() { return array( - 'ERR_USAGE_NO_THREAD_ID' => pht( - 'You must specify a thread id or thread PHID to query transactions '. + 'ERR_USAGE_NO_ROOM_ID' => pht( + 'You must specify a room id or room PHID to query transactions '. 'from.'), ); } protected function execute(ConduitAPIRequest $request) { $user = $request->getUser(); - $thread_id = $request->getValue('threadID'); - $thread_phid = $request->getValue('threadPHID'); + $room_id = $request->getValue('roomID'); + $room_phid = $request->getValue('roomPHID'); $limit = $request->getValue('limit'); $offset = $request->getValue('offset'); $query = id(new ConpherenceThreadQuery()) ->setViewer($user); - if ($thread_id) { - $query->withIDs(array($thread_id)); - } else if ($thread_phid) { - $query->withPHIDs(array($thread_phid)); + if ($room_id) { + $query->withIDs(array($room_id)); + } else if ($room_phid) { + $query->withPHIDs(array($room_phid)); } else { - throw new ConduitException('ERR_USAGE_NO_THREAD_ID'); + throw new ConduitException('ERR_USAGE_NO_ROOM_ID'); } $conpherence = $query->executeOne(); @@ -87,8 +87,8 @@ final class ConpherenceQueryTransactionConduitAPIMethod 'transactionMetadata' => $transaction->getMetadata(), 'authorPHID' => $transaction->getAuthorPHID(), 'dateCreated' => $transaction->getDateCreated(), - 'conpherenceID' => $conpherence->getID(), - 'conpherencePHID' => $conpherence->getPHID(), + 'roomID' => $conpherence->getID(), + 'roomPHID' => $conpherence->getPHID(), ); } return $data; diff --git a/src/applications/conpherence/conduit/ConpherenceUpdateThreadConduitAPIMethod.php b/src/applications/conpherence/conduit/ConpherenceUpdateThreadConduitAPIMethod.php index 66bbdab7e3..c7ea1405cd 100644 --- a/src/applications/conpherence/conduit/ConpherenceUpdateThreadConduitAPIMethod.php +++ b/src/applications/conpherence/conduit/ConpherenceUpdateThreadConduitAPIMethod.php @@ -8,7 +8,7 @@ final class ConpherenceUpdateThreadConduitAPIMethod } public function getMethodDescription() { - return pht('Update an existing conpherence thread.'); + return pht('Update an existing conpherence room.'); } protected function defineParamTypes() { @@ -28,13 +28,13 @@ final class ConpherenceUpdateThreadConduitAPIMethod protected function defineErrorTypes() { return array( - 'ERR_USAGE_NO_THREAD_ID' => pht( - 'You must specify a thread id or thread phid to query transactions '. + 'ERR_USAGE_NO_ROOM_ID' => pht( + 'You must specify a room id or room phid to query transactions '. 'from.'), - 'ERR_USAGE_THREAD_NOT_FOUND' => pht( - 'Thread does not exist or logged in user can not see it.'), + 'ERR_USAGE_ROOM_NOT_FOUND' => pht( + 'room does not exist or logged in user can not see it.'), 'ERR_USAGE_ONLY_SELF_REMOVE' => pht( - 'Only a user can remove themselves from a thread.'), + 'Only a user can remove themselves from a room.'), 'ERR_USAGE_NO_UPDATES' => pht( 'You must specify data that actually updates the conpherence.'), ); @@ -52,11 +52,11 @@ final class ConpherenceUpdateThreadConduitAPIMethod } else if ($phid) { $query->withPHIDs(array($phid)); } else { - throw new ConduitException('ERR_USAGE_NO_THREAD_ID'); + throw new ConduitException('ERR_USAGE_NO_ROOM_ID'); } $conpherence = $query->executeOne(); if (!$conpherence) { - throw new ConduitException('ERR_USAGE_THREAD_NOT_FOUND'); + throw new ConduitException('ERR_USAGE_ROOM_NOT_FOUND'); } $source = PhabricatorContentSource::newFromConduitRequest($request); diff --git a/src/applications/conpherence/controller/ConpherenceController.php b/src/applications/conpherence/controller/ConpherenceController.php index 11f92454fb..cbaf95a8b0 100644 --- a/src/applications/conpherence/controller/ConpherenceController.php +++ b/src/applications/conpherence/controller/ConpherenceController.php @@ -16,7 +16,7 @@ abstract class ConpherenceController extends PhabricatorController { $nav = new PHUIListView(); $nav->newLink( - pht('New Message'), + pht('New Room'), $this->getApplicationURI('new/')); $nav->addMenuItem( @@ -50,20 +50,20 @@ abstract class ConpherenceController extends PhabricatorController { ->addAction( id(new PHUIListItemView()) ->setName(pht('New Room')) - ->setHref($this->getApplicationURI('room/new/')) + ->setHref($this->getApplicationURI('new/')) ->setIcon('fa-plus-square') ->setWorkflow(true)); } else { $crumbs ->addAction( id(new PHUIListItemView()) - ->setName(pht('New Message')) + ->setName(pht('New Room')) ->setHref($this->getApplicationURI('new/')) ->setIcon('fa-plus-square') ->setWorkflow(true)) ->addAction( id(new PHUIListItemView()) - ->setName(pht('Thread')) + ->setName(pht('Room')) ->setHref('#') ->setIcon('fa-bars') ->setStyle('display: none;') @@ -80,14 +80,8 @@ abstract class ConpherenceController extends PhabricatorController { $crumbs = $this->buildApplicationCrumbs(); $data = $conpherence->getDisplayData($this->getViewer()); - if ($conpherence->getID() && $conpherence->getIsRoom()) { - $icon = $conpherence->getPolicyIconName($policy_objects); - } else { - $icon = null; - } $crumbs->addCrumb( id(new PHUICrumbView()) - ->setIcon($icon) ->setName($data['title']) ->setHref($this->getApplicationURI('update/'.$conpherence->getID().'/')) ->setWorkflow(true)); diff --git a/src/applications/conpherence/controller/ConpherenceListController.php b/src/applications/conpherence/controller/ConpherenceListController.php index ad672ff6d8..dbabc9b7d9 100644 --- a/src/applications/conpherence/controller/ConpherenceListController.php +++ b/src/applications/conpherence/controller/ConpherenceListController.php @@ -34,7 +34,7 @@ final class ConpherenceListController extends ConpherenceController { $title = pht('Conpherence'); $conpherence = null; - $limit = ConpherenceThreadListView::SEE_MORE_LIMIT * 5; + $limit = (ConpherenceThreadListView::SEE_MORE_LIMIT * 2) + 1; $all_participation = array(); $mode = $this->determineMode(); @@ -62,9 +62,28 @@ final class ConpherenceListController extends ConpherenceController { } else { $menu_participation = $cursor; } - $all_participation = - array($conpherence->getPHID() => $menu_participation) + - $all_participation; + + // check to see if the loaded conpherence is going to show up + // within the SEE_MORE_LIMIT amount of conpherences. + // If its not there, then we just pre-pend it as the "first" + // conpherence so folks have a navigation item in the menu. + $count = 0; + $found = false; + foreach ($all_participation as $phid => $curr_participation) { + if ($conpherence->getPHID() == $phid) { + $found = true; + break; + } + $count++; + if ($count > ConpherenceThreadListView::SEE_MORE_LIMIT) { + break; + } + } + if (!$found) { + $all_participation = + array($conpherence->getPHID() => $menu_participation) + + $all_participation; + } break; case self::UNSELECTED_MODE: default: @@ -93,22 +112,21 @@ final class ConpherenceListController extends ConpherenceController { ->setThreadView($thread_view) ->setRole('list'); if ($conpherence) { - $policy_objects = id(new PhabricatorPolicyQuery()) - ->setViewer($user) - ->setObject($conpherence) - ->execute(); - $layout->setHeader($this->buildHeaderPaneContent( - $conpherence, - $policy_objects)); $layout->setThread($conpherence); } else { - $thread = ConpherenceThread::initializeNewThread($user); - $thread->attachHandles(array()); - $thread->attachTransactions(array()); - $thread->makeEphemeral(); - $layout->setHeader( - $this->buildHeaderPaneContent($thread, array())); + // make a dummy conpherence so we can render something + $conpherence = ConpherenceThread::initializeNewRoom($user); + $conpherence->attachHandles(array()); + $conpherence->attachTransactions(array()); + $conpherence->makeEphemeral(); } + $policy_objects = id(new PhabricatorPolicyQuery()) + ->setViewer($user) + ->setObject($conpherence) + ->execute(); + $layout->setHeader($this->buildHeaderPaneContent( + $conpherence, + $policy_objects)); $response = $this->buildApplicationPage( $layout, array( diff --git a/src/applications/conpherence/controller/ConpherenceNewController.php b/src/applications/conpherence/controller/ConpherenceNewController.php deleted file mode 100644 index 102cf0e5ea..0000000000 --- a/src/applications/conpherence/controller/ConpherenceNewController.php +++ /dev/null @@ -1,90 +0,0 @@ -getUser(); - - $title = pht('New Message'); - $participants = array(); - $participant_prefill = null; - $message = ''; - $e_participants = null; - $e_message = null; - $errors = array(); - - // this comes from ajax requests from all over. should be a single phid. - - if ($request->isFormPost()) { - $participants = $request->getArr('participants'); - $message = $request->getStr('message'); - list($error_codes, $conpherence) = ConpherenceEditor::createThread( - $user, - $participants, - $conpherence_title = null, - $message, - PhabricatorContentSource::newFromRequest($request)); - - if ($error_codes) { - foreach ($error_codes as $error_code) { - switch ($error_code) { - case ConpherenceEditor::ERROR_EMPTY_MESSAGE: - $e_message = pht('Required'); - $errors[] = pht( - 'You can not send an empty message.'); - break; - case ConpherenceEditor::ERROR_EMPTY_PARTICIPANTS: - $e_participants = pht('Required'); - $errors[] = pht( - 'You must choose at least one recipient for your '. - 'message.'); - break; - } - } - } else { - return id(new AphrontRedirectResponse()) - ->setURI('/'.$conpherence->getMonogram()); - } - } else { - $participant_prefill = $request->getStr('participant'); - if ($participant_prefill) { - $participants[] = $participant_prefill; - } - } - - $submit_uri = $this->getApplicationURI('new/'); - $cancel_uri = $this->getApplicationURI(); - - $dialog = id(new AphrontDialogView()) - ->setWidth(AphrontDialogView::WIDTH_FORM) - ->setErrors($errors) - ->setUser($user) - ->setTitle($title) - ->addCancelButton($cancel_uri) - ->addSubmitButton(pht('Send Message')); - - $form = id(new AphrontFormView()) - ->setUser($user) - ->setFullWidth(true) - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setName('participants') - ->setValue($participants) - ->setUser($user) - ->setDatasource(new PhabricatorPeopleDatasource()) - ->setLabel(pht('To')) - ->setError($e_participants)) - ->appendChild( - id(new PhabricatorRemarkupControl()) - ->setUser($user) - ->setName('message') - ->setValue($message) - ->setLabel(pht('Message')) - ->setError($e_message)); - - $dialog->appendForm($form); - - return id(new AphrontDialogResponse())->setDialog($dialog); - } - -} diff --git a/src/applications/conpherence/controller/ConpherenceNewRoomController.php b/src/applications/conpherence/controller/ConpherenceNewRoomController.php index 28c51ea7d6..5578741e89 100644 --- a/src/applications/conpherence/controller/ConpherenceNewRoomController.php +++ b/src/applications/conpherence/controller/ConpherenceNewRoomController.php @@ -10,12 +10,18 @@ final class ConpherenceNewRoomController extends ConpherenceController { $validation_exception = null; $conpherence = ConpherenceThread::initializeNewRoom($user); + $participants = array(); if ($request->isFormPost()) { - + $editor = new ConpherenceEditor(); $xactions = array(); + + $participants = $request->getArr('participants'); + $participants[] = $user->getPHID(); + $participants = array_unique($participants); $xactions[] = id(new ConpherenceTransaction()) ->setTransactionType(ConpherenceTransaction::TYPE_PARTICIPANTS) - ->setNewValue(array('+' => array($user->getPHID()))); + ->setNewValue(array('+' => $participants)); + $xactions[] = id(new ConpherenceTransaction()) ->setTransactionType(ConpherenceTransaction::TYPE_TITLE) ->setNewValue($request->getStr('title')); @@ -29,8 +35,17 @@ final class ConpherenceNewRoomController extends ConpherenceController { ->setTransactionType(PhabricatorTransactions::TYPE_JOIN_POLICY) ->setNewValue($request->getStr('joinPolicy')); + $message = $request->getStr('message'); + if ($message) { + $message_xactions = $editor->generateTransactionsFromText( + $user, + $conpherence, + $message); + $xactions = array_merge($xactions, $message_xactions); + } + try { - id(new ConpherenceEditor()) + $editor ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true) ->setActor($user) @@ -47,6 +62,10 @@ final class ConpherenceNewRoomController extends ConpherenceController { $conpherence->setEditPolicy($request->getStr('editPolicy')); $conpherence->setJoinPolicy($request->getStr('joinPolicy')); } + } else { + if ($request->getStr('participant')) { + $participants[] = $request->getStr('participant'); + } } $policies = id(new PhabricatorPolicyQuery()) @@ -54,7 +73,7 @@ final class ConpherenceNewRoomController extends ConpherenceController { ->setObject($conpherence) ->execute(); - $submit_uri = $this->getApplicationURI('room/new/'); + $submit_uri = $this->getApplicationURI('new/'); $cancel_uri = $this->getApplicationURI('search/'); $dialog = $this->newDialog() @@ -67,13 +86,19 @@ final class ConpherenceNewRoomController extends ConpherenceController { $form = id(new PHUIFormLayoutView()) ->setUser($user) - ->setFullWidth(true) ->appendChild( id(new AphrontFormTextControl()) ->setError($e_title) - ->setLabel(pht('Title')) + ->setLabel(pht('Name')) ->setName('title') ->setValue($request->getStr('title'))) + ->appendChild( + id(new AphrontFormTokenizerControl()) + ->setName('participants') + ->setUser($user) + ->setDatasource(new PhabricatorPeopleDatasource()) + ->setValue($participants) + ->setLabel(pht('Other Participants'))) ->appendChild( id(new AphrontFormPolicyControl()) ->setName('viewPolicy') @@ -91,7 +116,12 @@ final class ConpherenceNewRoomController extends ConpherenceController { ->setName('joinPolicy') ->setPolicyObject($conpherence) ->setCapability(PhabricatorPolicyCapability::CAN_JOIN) - ->setPolicies($policies)); + ->setPolicies($policies)) + ->appendChild( + id(new PhabricatorRemarkupControl()) + ->setUser($user) + ->setName('message') + ->setLabel(pht('First Message'))); $dialog->appendChild($form); diff --git a/src/applications/conpherence/controller/ConpherenceNotificationPanelController.php b/src/applications/conpherence/controller/ConpherenceNotificationPanelController.php index ab5b7470fc..63e777818c 100644 --- a/src/applications/conpherence/controller/ConpherenceNotificationPanelController.php +++ b/src/applications/conpherence/controller/ConpherenceNotificationPanelController.php @@ -83,7 +83,7 @@ final class ConpherenceNotificationPanelController array( 'href' => '/conpherence/', ), - pht('Messages')), + pht('Rooms')), $content); $unread = id(new ConpherenceParticipantCountQuery()) diff --git a/src/applications/conpherence/controller/ConpherenceRoomListController.php b/src/applications/conpherence/controller/ConpherenceRoomListController.php index 43c36d20d1..704f210781 100644 --- a/src/applications/conpherence/controller/ConpherenceRoomListController.php +++ b/src/applications/conpherence/controller/ConpherenceRoomListController.php @@ -33,7 +33,7 @@ final class ConpherenceRoomListController extends ConpherenceController { $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); if ($for_app) { - $nav->addFilter('room/new/', pht('Create Room')); + $nav->addFilter('new/', pht('Create Room')); } id(new ConpherenceThreadSearchEngine()) diff --git a/src/applications/conpherence/controller/ConpherenceUpdateController.php b/src/applications/conpherence/controller/ConpherenceUpdateController.php index c88aee23d7..0739c4054c 100644 --- a/src/applications/conpherence/controller/ConpherenceUpdateController.php +++ b/src/applications/conpherence/controller/ConpherenceUpdateController.php @@ -188,17 +188,15 @@ final class ConpherenceUpdateController $xactions[] = id(new ConpherenceTransaction()) ->setTransactionType(ConpherenceTransaction::TYPE_TITLE) ->setNewValue($title); - if ($conpherence->getIsRoom()) { - $xactions[] = id(new ConpherenceTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) - ->setNewValue($request->getStr('viewPolicy')); - $xactions[] = id(new ConpherenceTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY) - ->setNewValue($request->getStr('editPolicy')); - $xactions[] = id(new ConpherenceTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_JOIN_POLICY) - ->setNewValue($request->getStr('joinPolicy')); - } + $xactions[] = id(new ConpherenceTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) + ->setNewValue($request->getStr('viewPolicy')); + $xactions[] = id(new ConpherenceTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY) + ->setNewValue($request->getStr('editPolicy')); + $xactions[] = id(new ConpherenceTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_JOIN_POLICY) + ->setNewValue($request->getStr('joinPolicy')); if (!$request->getExists('force_ajax')) { $response_mode = 'redirect'; } @@ -245,8 +243,11 @@ final class ConpherenceUpdateController ->setContent($content); break; case 'go-home': - return id(new AphrontRedirectResponse()) - ->setURI($this->getApplicationURI()); + $content = array( + 'href' => $this->getApplicationURI(), + ); + return id(new AphrontAjaxResponse()) + ->setContent($content); break; case 'redirect': default: @@ -323,18 +324,21 @@ final class ConpherenceUpdateController $user = $request->getUser(); $remove_person = $request->getStr('remove_person'); $participants = $conpherence->getParticipants(); - if ($conpherence->getIsRoom()) { - $message = pht( - 'Are you sure you want to remove yourself from this room?'); - } else { - $message = pht( - 'Are you sure you want to remove yourself from this thread?'); + + $message = pht( + 'Are you sure you want to leave this room?'); + $test_conpherence = clone $conpherence; + $test_conpherence->attachParticipants(array()); + if (!PhabricatorPolicyFilter::hasCapability( + $user, + $test_conpherence, + PhabricatorPolicyCapability::CAN_VIEW)) { if (count($participants) == 1) { $message .= pht( - 'The thread will be inaccessible forever and ever.'); + ' The room will be inaccessible forever and ever.'); } else { $message .= pht( - 'Someone else in the thread can add you back later.'); + ' Someone else in the room can add you back later.'); } } $body = phutil_tag( @@ -345,7 +349,7 @@ final class ConpherenceUpdateController require_celerity_resource('conpherence-update-css'); return id(new AphrontDialogView()) - ->setTitle(pht('Remove Participants')) + ->setTitle(pht('Leave Room')) ->addHiddenInput('action', 'remove_person') ->addHiddenInput('remove_person', $remove_person) ->addHiddenInput( @@ -362,6 +366,7 @@ final class ConpherenceUpdateController $request = $this->getRequest(); $user = $request->getUser(); + $title = pht('Update Room'); $form = id(new PHUIFormLayoutView()) ->appendChild($error_view) ->appendChild( @@ -399,14 +404,13 @@ final class ConpherenceUpdateController ->setLabel(pht('Image'))); } - if ($conpherence->getIsRoom()) { - $title = pht('Update Room'); - $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($user) - ->setObject($conpherence) - ->execute(); + $policies = id(new PhabricatorPolicyQuery()) + ->setViewer($user) + ->setObject($conpherence) + ->execute(); - $form->appendChild( + $form + ->appendChild( id(new AphrontFormPolicyControl()) ->setName('viewPolicy') ->setPolicyObject($conpherence) @@ -424,9 +428,6 @@ final class ConpherenceUpdateController ->setPolicyObject($conpherence) ->setCapability(PhabricatorPolicyCapability::CAN_JOIN) ->setPolicies($policies)); - } else { - $title = pht('Update Thread'); - } require_celerity_resource('conpherence-update-css'); $view = id(new AphrontDialogView()) @@ -520,7 +521,7 @@ final class ConpherenceUpdateController $nav_item = id(new ConpherenceThreadListView()) ->setUser($user) ->setBaseURI($this->getApplicationURI()) - ->renderSingleThread($conpherence); + ->renderSingleThread($conpherence, $policy_objects); $nav_item = hsprintf('%s', $nav_item); break; case ConpherenceUpdateActions::MESSAGE: diff --git a/src/applications/conpherence/editor/ConpherenceEditor.php b/src/applications/conpherence/editor/ConpherenceEditor.php index c9445216fe..299b799d3e 100644 --- a/src/applications/conpherence/editor/ConpherenceEditor.php +++ b/src/applications/conpherence/editor/ConpherenceEditor.php @@ -10,7 +10,7 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { } public function getEditorObjectsDescription() { - return pht('Conpherence Threads'); + return pht('Conpherence Rooms'); } public static function createThread( @@ -20,7 +20,7 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { $message, PhabricatorContentSource $source) { - $conpherence = ConpherenceThread::initializeNewThread($creator); + $conpherence = ConpherenceThread::initializeNewRoom($creator); $files = array(); $errors = array(); if (empty($participant_phids)) { @@ -456,7 +456,7 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { $is_leave = (($rem === array($actor_phid)) && !$add); if ($is_join) { - // You need CAN_JOIN to join a thread / room. + // You need CAN_JOIN to join a room. PhabricatorPolicyFilter::requireCapability( $this->requireActor(), $object, @@ -583,11 +583,7 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { $href = PhabricatorEnv::getProductionURI( '/'.$object->getMonogram().'?settings'); - if ($object->getIsRoom()) { - $label = pht('EMAIL PREFERENCES FOR THIS ROOM'); - } else { - $label = pht('EMAIL PREFERENCES FOR THIS MESSAGE'); - } + $label = pht('EMAIL PREFERENCES FOR THIS ROOM'); $body->addLinkSection($label, $href); } @@ -644,19 +640,15 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { switch ($type) { case ConpherenceTransaction::TYPE_TITLE: - if (!$object->getIsRoom()) { - continue; + if (empty($xactions)) { + break; } $missing = $this->validateIsEmptyTextField( $object->getTitle(), $xactions); if ($missing) { - if ($object->getIsRoom()) { - $detail = pht('Room title is required.'); - } else { - $detail = pht('Thread title can not be blank.'); - } + $detail = pht('Room title is required.'); $error = new PhabricatorApplicationTransactionValidationError( $type, pht('Required'), @@ -704,7 +696,7 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { $errors[] = new PhabricatorApplicationTransactionValidationError( $type, pht('Invalid'), - pht('New thread member "%s" is not a valid user.', $phid), + pht('New room participant "%s" is not a valid user.', $phid), $xaction); } } diff --git a/src/applications/conpherence/events/ConpherenceHovercardEventListener.php b/src/applications/conpherence/events/ConpherenceHovercardEventListener.php index 616af030ea..dcf4f08294 100644 --- a/src/applications/conpherence/events/ConpherenceHovercardEventListener.php +++ b/src/applications/conpherence/events/ConpherenceHovercardEventListener.php @@ -30,8 +30,8 @@ final class ConpherenceHovercardEventListener extends PhabricatorEventListener { return; } - $conpherence_uri = new PhutilURI( - '/conpherence/new/?participant='.$user->getPHID()); + $conpherence_uri = id(new PhutilURI('/conpherence/new/')) + ->setQueryParam('participant', $user->getPHID()); $name = pht('Send a Message'); $hovercard->addAction($name, $conpherence_uri, true); diff --git a/src/applications/conpherence/mail/ConpherenceCreateThreadMailReceiver.php b/src/applications/conpherence/mail/ConpherenceCreateThreadMailReceiver.php index c7dc69ea87..aacf4426d4 100644 --- a/src/applications/conpherence/mail/ConpherenceCreateThreadMailReceiver.php +++ b/src/applications/conpherence/mail/ConpherenceCreateThreadMailReceiver.php @@ -53,7 +53,7 @@ final class ConpherenceCreateThreadMailReceiver $phids = mpull($users, 'getPHID'); $conpherence = id(new ConpherenceReplyHandler()) - ->setMailReceiver(ConpherenceThread::initializeNewThread($sender)) + ->setMailReceiver(ConpherenceThread::initializeNewRoom($sender)) ->setMailAddedParticipantPHIDs($phids) ->setActor($sender) ->setExcludeMailRecipientPHIDs($mail->loadExcludeMailRecipientPHIDs()) diff --git a/src/applications/conpherence/phid/PhabricatorConpherenceThreadPHIDType.php b/src/applications/conpherence/phid/PhabricatorConpherenceThreadPHIDType.php index 81a5a49043..98f0d74797 100644 --- a/src/applications/conpherence/phid/PhabricatorConpherenceThreadPHIDType.php +++ b/src/applications/conpherence/phid/PhabricatorConpherenceThreadPHIDType.php @@ -5,7 +5,7 @@ final class PhabricatorConpherenceThreadPHIDType extends PhabricatorPHIDType { const TYPECONST = 'CONP'; public function getTypeName() { - return pht('Conpherence Thread'); + return pht('Conpherence Room'); } public function newObject() { diff --git a/src/applications/conpherence/policyrule/ConpherenceThreadMembersPolicyRule.php b/src/applications/conpherence/policyrule/ConpherenceThreadMembersPolicyRule.php index 658ee42bdb..9cf2c2861f 100644 --- a/src/applications/conpherence/policyrule/ConpherenceThreadMembersPolicyRule.php +++ b/src/applications/conpherence/policyrule/ConpherenceThreadMembersPolicyRule.php @@ -8,15 +8,19 @@ final class ConpherenceThreadMembersPolicyRule } public function getObjectPolicyName() { - return pht('Thread Members'); + return pht('Room Participants'); } public function getPolicyExplanation() { - return pht('Members of this thread can take this action.'); + return pht('Participants in this room can take this action.'); } public function getRuleDescription() { - return pht('thread members'); + return pht('room participants'); + } + + public function getObjectPolicyIcon() { + return 'fa-comments'; } public function canApplyToObject(PhabricatorPolicyInterface $object) { diff --git a/src/applications/conpherence/query/ConpherenceThreadQuery.php b/src/applications/conpherence/query/ConpherenceThreadQuery.php index a04037cf6c..7006ee759d 100644 --- a/src/applications/conpherence/query/ConpherenceThreadQuery.php +++ b/src/applications/conpherence/query/ConpherenceThreadQuery.php @@ -8,7 +8,6 @@ final class ConpherenceThreadQuery private $phids; private $ids; private $participantPHIDs; - private $isRoom; private $needParticipants; private $needWidgetData; private $needCropPics; @@ -71,11 +70,6 @@ final class ConpherenceThreadQuery return $this; } - public function withIsRoom($bool) { - $this->isRoom = $bool; - return $this; - } - public function setAfterTransactionID($id) { $this->afterTransactionID = $id; return $this; @@ -166,16 +160,6 @@ final class ConpherenceThreadQuery id(new ConpherenceParticipant())->getTableName()); } - $viewer = $this->getViewer(); - if ($this->shouldJoinForViewer($viewer)) { - $joins[] = qsprintf( - $conn_r, - 'LEFT JOIN %T v ON v.conpherencePHID = conpherence_thread.phid '. - 'AND v.participantPHID = %s', - id(new ConpherenceParticipant())->getTableName(), - $viewer->getPHID()); - } - if (strlen($this->fulltext)) { $joins[] = qsprintf( $conn_r, @@ -187,15 +171,6 @@ final class ConpherenceThreadQuery return implode(' ', $joins); } - private function shouldJoinForViewer(PhabricatorUser $viewer) { - if ($viewer->isLoggedIn() && - $this->ids === null && - $this->phids === null) { - return true; - } - return false; - } - protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { $where = array(); @@ -222,13 +197,6 @@ final class ConpherenceThreadQuery $this->participantPHIDs); } - if ($this->isRoom !== null) { - $where[] = qsprintf( - $conn_r, - 'conpherence_thread.isRoom = %d', - (int)$this->isRoom); - } - if (strlen($this->fulltext)) { $where[] = qsprintf( $conn_r, @@ -236,17 +204,6 @@ final class ConpherenceThreadQuery $this->fulltext); } - $viewer = $this->getViewer(); - if ($this->shouldJoinForViewer($viewer)) { - $where[] = qsprintf( - $conn_r, - 'conpherence_thread.isRoom = 1 OR v.participantPHID IS NOT NULL'); - } else if ($this->phids === null && $this->ids === null) { - $where[] = qsprintf( - $conn_r, - 'conpherence_thread.isRoom = 1'); - } - return $this->formatWhereClause($where); } diff --git a/src/applications/conpherence/query/ConpherenceThreadSearchEngine.php b/src/applications/conpherence/query/ConpherenceThreadSearchEngine.php index fb6424bae7..7fe282fe19 100644 --- a/src/applications/conpherence/query/ConpherenceThreadSearchEngine.php +++ b/src/applications/conpherence/query/ConpherenceThreadSearchEngine.php @@ -4,7 +4,7 @@ final class ConpherenceThreadSearchEngine extends PhabricatorApplicationSearchEngine { public function getResultTypeDescription() { - return pht('Threads'); + return pht('Rooms'); } public function getApplicationClassName() { @@ -20,10 +20,6 @@ final class ConpherenceThreadSearchEngine $saved->setParameter('fulltext', $request->getStr('fulltext')); - $saved->setParameter( - 'threadType', - $request->getStr('threadType')); - return $saved; } @@ -41,21 +37,6 @@ final class ConpherenceThreadSearchEngine $query->withFulltext($fulltext); } - $thread_type = $saved->getParameter('threadType'); - if (idx($this->getTypeOptions(), $thread_type)) { - switch ($thread_type) { - case 'rooms': - $query->withIsRoom(true); - break; - case 'messages': - $query->withIsRoom(false); - break; - case 'both': - $query->withIsRoom(null); - break; - } - } - return $query; } @@ -77,13 +58,7 @@ final class ConpherenceThreadSearchEngine id(new AphrontFormTextControl()) ->setName('fulltext') ->setLabel(pht('Contains Words')) - ->setValue($fulltext)) - ->appendControl( - id(new AphrontFormSelectControl()) - ->setLabel(pht('Type')) - ->setName('threadType') - ->setOptions($this->getTypeOptions()) - ->setValue($saved->getParameter('threadType'))); + ->setValue($fulltext)); } protected function getURI($path) { @@ -99,7 +74,6 @@ final class ConpherenceThreadSearchEngine if ($this->requireViewer()->isLoggedIn()) { $names['participant'] = pht('Joined Rooms'); - $names['messages'] = pht('All Messages'); } return $names; @@ -112,15 +86,8 @@ final class ConpherenceThreadSearchEngine switch ($query_key) { case 'all': - $query->setParameter('threadType', 'rooms'); return $query; case 'participant': - $query->setParameter('threadType', 'rooms'); - return $query->setParameter( - 'participantPHIDs', - array($this->requireViewer()->getPHID())); - case 'messages': - $query->setParameter('threadType', 'messages'); return $query->setParameter( 'participantPHIDs', array($this->requireViewer()->getPHID())); @@ -145,7 +112,7 @@ final class ConpherenceThreadSearchEngine $viewer = $this->requireViewer(); - $policy_objects = ConpherenceThread::loadPolicyObjects( + $policy_objects = ConpherenceThread::loadViewPolicyObjects( $viewer, $conpherences); @@ -192,11 +159,7 @@ final class ConpherenceThreadSearchEngine $title = $conpherence->getDisplayTitle($viewer); $monogram = $conpherence->getMonogram(); - if ($conpherence->getIsRoom()) { - $icon_name = $conpherence->getPolicyIconName($policy_objects); - } else { - $icon_name = 'fa-envelope-o'; - } + $icon_name = $conpherence->getPolicyIconName($policy_objects); $icon = id(new PHUIIconView()) ->setIconFont($icon_name); $item = id(new PHUIObjectItemView()) @@ -260,14 +223,6 @@ final class ConpherenceThreadSearchEngine return $result; } - private function getTypeOptions() { - return array( - 'rooms' => pht('Rooms'), - 'messages' => pht('Messages'), - 'both' => pht('Both'), - ); - } - private function loadContextMessages(array $threads, $fulltext) { $phids = mpull($threads, 'getPHID'); diff --git a/src/applications/conpherence/storage/ConpherenceThread.php b/src/applications/conpherence/storage/ConpherenceThread.php index 2600e719e7..376a83899f 100644 --- a/src/applications/conpherence/storage/ConpherenceThread.php +++ b/src/applications/conpherence/storage/ConpherenceThread.php @@ -9,7 +9,6 @@ final class ConpherenceThread extends ConpherenceDAO protected $title; protected $imagePHIDs = array(); - protected $isRoom = 0; protected $messageCount; protected $recentParticipantPHIDs = array(); protected $mailKey; @@ -24,30 +23,18 @@ final class ConpherenceThread extends ConpherenceDAO private $widgetData = self::ATTACHABLE; private $images = self::ATTACHABLE; - public static function initializeNewThread(PhabricatorUser $sender) { + public static function initializeNewRoom(PhabricatorUser $sender) { + $default_policy = id(new ConpherenceThreadMembersPolicyRule()) + ->getObjectPolicyFullKey(); return id(new ConpherenceThread()) ->setMessageCount(0) ->setTitle('') ->attachParticipants(array()) ->attachFilePHIDs(array()) ->attachImages(array()) - ->setViewPolicy(PhabricatorPolicies::POLICY_USER) - ->setEditPolicy(PhabricatorPolicies::POLICY_USER) - ->setJoinPolicy(PhabricatorPolicies::POLICY_USER); - } - - public static function initializeNewRoom(PhabricatorUser $creator) { - - return id(new ConpherenceThread()) - ->setIsRoom(1) - ->setMessageCount(0) - ->setTitle('') - ->attachParticipants(array()) - ->attachFilePHIDs(array()) - ->attachImages(array()) - ->setViewPolicy(PhabricatorPolicies::POLICY_USER) - ->setEditPolicy($creator->getPHID()) - ->setJoinPolicy(PhabricatorPolicies::POLICY_USER); + ->setViewPolicy($default_policy) + ->setEditPolicy($default_policy) + ->setJoinPolicy($default_policy); } protected function getConfiguration() { @@ -59,15 +46,11 @@ final class ConpherenceThread extends ConpherenceDAO ), self::CONFIG_COLUMN_SCHEMA => array( 'title' => 'text255?', - 'isRoom' => 'bool', 'messageCount' => 'uint64', 'mailKey' => 'text20', 'joinPolicy' => 'policy', ), self::CONFIG_KEY_SCHEMA => array( - 'key_room' => array( - 'columns' => array('isRoom', 'dateModified'), - ), 'key_phid' => null, 'phid' => array( 'columns' => array('phid'), @@ -214,7 +197,7 @@ final class ConpherenceThread extends ConpherenceDAO return $title; } - return pht('Private Correspondence'); + return pht('Private Room'); } /** @@ -382,15 +365,13 @@ final class ConpherenceThread extends ConpherenceDAO } public function getPolicy($capability) { - if ($this->getIsRoom()) { - switch ($capability) { - case PhabricatorPolicyCapability::CAN_VIEW: - return $this->getViewPolicy(); - case PhabricatorPolicyCapability::CAN_EDIT: - return $this->getEditPolicy(); - case PhabricatorPolicyCapability::CAN_JOIN: - return $this->getJoinPolicy(); - } + switch ($capability) { + case PhabricatorPolicyCapability::CAN_VIEW: + return $this->getViewPolicy(); + case PhabricatorPolicyCapability::CAN_EDIT: + return $this->getEditPolicy(); + case PhabricatorPolicyCapability::CAN_JOIN: + return $this->getJoinPolicy(); } return PhabricatorPolicies::POLICY_NOONE; } @@ -401,12 +382,10 @@ final class ConpherenceThread extends ConpherenceDAO return true; } - if ($this->getIsRoom()) { - switch ($capability) { - case PhabricatorPolicyCapability::CAN_EDIT: - case PhabricatorPolicyCapability::CAN_JOIN: - return false; - } + switch ($capability) { + case PhabricatorPolicyCapability::CAN_EDIT: + case PhabricatorPolicyCapability::CAN_JOIN: + return false; } $participants = $this->getParticipants(); @@ -414,35 +393,28 @@ final class ConpherenceThread extends ConpherenceDAO } public function describeAutomaticCapability($capability) { - if ($this->getIsRoom()) { - switch ($capability) { - case PhabricatorPolicyCapability::CAN_VIEW: - return pht('Participants in a room can always view it.'); - break; - } - } else { - return pht('Participants in a thread can always view and edit it.'); + switch ($capability) { + case PhabricatorPolicyCapability::CAN_VIEW: + return pht('Participants in a room can always view it.'); + break; } } - public static function loadPolicyObjects( + public static function loadViewPolicyObjects( PhabricatorUser $viewer, array $conpherences) { assert_instances_of($conpherences, __CLASS__); - $grouped = mgroup($conpherences, 'getIsRoom'); - $rooms = idx($grouped, 1, array()); - $policies = array(); - foreach ($rooms as $room) { - $policies[] = $room->getViewPolicy(); + foreach ($conpherences as $room) { + $policies[$room->getViewPolicy()] = 1; } $policy_objects = array(); if ($policies) { $policy_objects = id(new PhabricatorPolicyQuery()) ->setViewer($viewer) - ->withPHIDs($policies) + ->withPHIDs(array_keys($policies)) ->execute(); } @@ -452,13 +424,7 @@ final class ConpherenceThread extends ConpherenceDAO public function getPolicyIconName(array $policy_objects) { assert_instances_of($policy_objects, 'PhabricatorPolicy'); - if ($this->getIsRoom()) { - $icon = $policy_objects[$this->getViewPolicy()]->getIcon(); - } else if (count($this->getRecentParticipantPHIDs()) > 2) { - $icon = 'fa-users'; - } else { - $icon = 'fa-user'; - } + $icon = $policy_objects[$this->getViewPolicy()]->getIcon(); return $icon; } diff --git a/src/applications/conpherence/storage/ConpherenceTransaction.php b/src/applications/conpherence/storage/ConpherenceTransaction.php index d4af549d37..ba49cdf9b4 100644 --- a/src/applications/conpherence/storage/ConpherenceTransaction.php +++ b/src/applications/conpherence/storage/ConpherenceTransaction.php @@ -63,11 +63,7 @@ final class ConpherenceTransaction extends PhabricatorApplicationTransaction { case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_JOIN_POLICY: case self::TYPE_PICTURE: - if ($this->getObject()->getIsRoom()) { - return $this->getRoomTitle(); - } else { - return $this->getThreadTitle(); - } + return $this->getRoomTitle(); break; case self::TYPE_FILES: $add = array_diff($new, $old); @@ -180,62 +176,6 @@ final class ConpherenceTransaction extends PhabricatorApplicationTransaction { } } - private function getThreadTitle() { - $author_phid = $this->getAuthorPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_TITLE: - if ($old && $new) { - $title = pht( - '%s renamed this thread from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $old, - $new); - } else if ($old) { - $title = pht( - '%s deleted the thread name "%s".', - $this->renderHandleLink($author_phid), - $old); - } else { - $title = pht( - '%s named this thread "%s".', - $this->renderHandleLink($author_phid), - $new); - } - return $title; - break; - case self::TYPE_PICTURE: - return pht( - '%s updated the room image.', - $this->renderHandleLink($author_phid)); - break; - case PhabricatorTransactions::TYPE_VIEW_POLICY: - return pht( - '%s changed the visibility of this thread from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $this->renderPolicyName($old, 'old'), - $this->renderPolicyName($new, 'new')); - break; - case PhabricatorTransactions::TYPE_EDIT_POLICY: - return pht( - '%s changed the edit policy of this thread from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $this->renderPolicyName($old, 'old'), - $this->renderPolicyName($new, 'new')); - break; - case PhabricatorTransactions::TYPE_JOIN_POLICY: - return pht( - '%s changed the join policy of this thread from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $this->renderPolicyName($old, 'old'), - $this->renderPolicyName($new, 'new')); - break; - } - } - public function getRequiredHandlePHIDs() { $phids = parent::getRequiredHandlePHIDs(); diff --git a/src/applications/conpherence/view/ConpherenceDurableColumnView.php b/src/applications/conpherence/view/ConpherenceDurableColumnView.php index 10efaed7af..8257ee31f1 100644 --- a/src/applications/conpherence/view/ConpherenceDurableColumnView.php +++ b/src/applications/conpherence/view/ConpherenceDurableColumnView.php @@ -118,21 +118,9 @@ final class ConpherenceDurableColumnView extends AphrontTagView { 'quicksandConfig' => $this->getQuicksandConfig(), )); - $policies = array(); - $conpherences = $this->getConpherences(); - foreach ($conpherences as $conpherence) { - if (!$conpherence->getIsRoom()) { - continue; - } - $policies[] = $conpherence->getViewPolicy(); - } - $policy_objects = array(); - if ($policies) { - $policy_objects = id(new PhabricatorPolicyQuery()) - ->setViewer($this->getUser()) - ->withPHIDs($policies) - ->execute(); - } + $policy_objects = ConpherenceThread::loadViewPolicyObjects( + $this->getUser(), + $this->getConpherences()); $this->setPolicyObjects($policy_objects); $classes = array(); @@ -223,13 +211,10 @@ final class ConpherenceDurableColumnView extends AphrontTagView { assert_instances_of($policy_objects, 'PhabricatorPolicy'); - $icon = null; - if ($conpherence->getIsRoom()) { - $icon = $conpherence->getPolicyIconName($policy_objects); - $icon = id(new PHUIIconView()) - ->addClass('mmr') - ->setIconFont($icon); - } + $icon = $conpherence->getPolicyIconName($policy_objects); + $icon = id(new PHUIIconView()) + ->addClass('mmr') + ->setIconFont($icon); return $icon; } @@ -390,11 +375,6 @@ final class ConpherenceDurableColumnView extends AphrontTagView { } private function getHeaderActionsConfig(ConpherenceThread $conpherence) { - if ($conpherence->getIsRoom()) { - $rename_label = pht('Edit Room'); - } else { - $rename_label = pht('Rename Thread'); - } $can_edit = PhabricatorPolicyFilter::hasCapability( $this->getUser(), $conpherence, @@ -409,7 +389,7 @@ final class ConpherenceDurableColumnView extends AphrontTagView { 'key' => ConpherenceUpdateActions::ADD_PERSON, ), array( - 'name' => $rename_label, + 'name' => pht('Edit Room'), 'disabled' => !$can_edit, 'href' => '/conpherence/update/'.$conpherence->getID().'/?nopic', 'icon' => 'fa-pencil', @@ -444,7 +424,7 @@ final class ConpherenceDurableColumnView extends AphrontTagView { array( 'class' => 'mmb', ), - pht('You do not have any messages yet.')), + pht('You are not in any rooms yet.')), javelin_tag( 'a', array( @@ -452,7 +432,7 @@ final class ConpherenceDurableColumnView extends AphrontTagView { 'class' => 'button grey', 'sigil' => 'workflow', ), - pht('Send a Message')), + pht('Create a Room')), ); } diff --git a/src/applications/conpherence/view/ConpherenceLayoutView.php b/src/applications/conpherence/view/ConpherenceLayoutView.php index 30bdd46493..2549e556d4 100644 --- a/src/applications/conpherence/view/ConpherenceLayoutView.php +++ b/src/applications/conpherence/view/ConpherenceLayoutView.php @@ -137,7 +137,7 @@ final class ConpherenceLayoutView extends AphrontView { array( 'class' => 'text', ), - pht('You do not have any messages yet.')), + pht('You are not in any rooms yet.')), javelin_tag( 'a', array( @@ -145,7 +145,7 @@ final class ConpherenceLayoutView extends AphrontView { 'class' => 'button grey', 'sigil' => 'workflow', ), - pht('Send a Message')), + pht('Create a Room')), )), javelin_tag( 'div', diff --git a/src/applications/conpherence/view/ConpherenceThreadListView.php b/src/applications/conpherence/view/ConpherenceThreadListView.php index be8c6e4558..668e6f9558 100644 --- a/src/applications/conpherence/view/ConpherenceThreadListView.php +++ b/src/applications/conpherence/view/ConpherenceThreadListView.php @@ -2,7 +2,7 @@ final class ConpherenceThreadListView extends AphrontView { - const SEE_MORE_LIMIT = 5; + const SEE_MORE_LIMIT = 15; private $baseURI; private $threads; @@ -25,40 +25,25 @@ final class ConpherenceThreadListView extends AphrontView { ->addClass('conpherence-menu') ->setID('conpherence-menu'); - $policy_objects = ConpherenceThread::loadPolicyObjects( + $policy_objects = ConpherenceThread::loadViewPolicyObjects( $this->getUser(), $this->threads); - $grouped = mgroup($this->threads, 'getIsRoom'); - $rooms = idx($grouped, 1, array()); - $this->addRoomsToMenu($menu, $rooms, $policy_objects); - $messages = idx($grouped, 0, array()); - $this->addMessagesToMenu($menu, $messages); + $this->addRoomsToMenu($menu, $this->threads, $policy_objects); return $menu; } - public function renderSingleThread(ConpherenceThread $thread) { - $policy_objects = id(new PhabricatorPolicyQuery()) - ->setViewer($this->getUser()) - ->setObject($thread) - ->execute(); + public function renderSingleThread( + ConpherenceThread $thread, + array $policy_objects) { + assert_instances_of($policy_objects, 'PhabricatorPolicy'); return $this->renderThread($thread, $policy_objects); } - public function renderThreadsHTML() { - $thread_html = array(); - - foreach ($this->threads as $thread) { - $thread_html[] = $this->renderSingleThread($thread); - } - - return phutil_implode_html('', $thread_html); - } - private function renderThreadItem( ConpherenceThread $thread, - $policy_objects = array()) { + array $policy_objects) { return id(new PHUIListItemView()) ->setType(PHUIListItemView::TYPE_CUSTOM) ->setName($this->renderThread($thread, $policy_objects)); @@ -72,12 +57,9 @@ final class ConpherenceThreadListView extends AphrontView { $uri = '/'.$thread->getMonogram(); $data = $thread->getDisplayData($user); - $icon = null; - if ($thread->getIsRoom()) { - $icon = id(new PHUIIconView()) - ->addClass('msr') - ->setIconFont($thread->getPolicyIconName($policy_objects)); - } + $icon = id(new PHUIIconView()) + ->addClass('msr') + ->setIconFont($thread->getPolicyIconName($policy_objects)); $title = phutil_tag( 'span', array(), @@ -141,7 +123,7 @@ final class ConpherenceThreadListView extends AphrontView { $create_item = id(new PHUIListItemView()) ->setType(PHUIListItemView::TYPE_LINK) - ->setHref('/conpherence/room/new/') + ->setHref('/conpherence/new/') ->setWorkflow(true) ->setName(pht('Create a Room')); $menu->addMenuItem($create_item); @@ -153,25 +135,6 @@ final class ConpherenceThreadListView extends AphrontView { return $menu; } - private function addMessagesToMenu( - PHUIListView $menu, - array $conpherences) { - - $header = $this->renderMenuItemHeader( - pht('Messages'), - 'conpherence-message-list-header'); - $menu->addMenuItem($header); - - if (empty($conpherences)) { - $menu->addMenuItem($this->getNoMessagesMenuItem()); - return $menu; - } - - $this->addThreadsToMenu($menu, $conpherences, array()); - - return $menu; - } - private function addThreadsToMenu( PHUIListView $menu, array $threads, @@ -187,21 +150,14 @@ final class ConpherenceThreadListView extends AphrontView { $more_threads = array_slice($threads, self::SEE_MORE_LIMIT); } - $is_room = false; foreach ($show_threads as $thread) { $item = $this->renderThreadItem($thread, $policy_objects); $menu->addMenuItem($item); - $is_room = $thread->getIsRoom(); } if ($more_threads) { - if ($is_room) { - $search_uri = '/conpherence/search/query/participant/'; - $sigil = 'more-room'; - } else { - $search_uri = '/conpherence/search/query/messages/'; - $sigil = 'more-message'; - } + $search_uri = '/conpherence/search/query/participant/'; + $sigil = 'more-room'; $more_item = id(new PHUIListItemView()) ->setType(PHUIListItemView::TYPE_LINK) @@ -251,19 +207,6 @@ final class ConpherenceThreadListView extends AphrontView { return $item; } - private function getNoMessagesMenuItem() { - $message = phutil_tag( - 'div', - array( - 'class' => 'no-conpherences-menu-item', - ), - pht('No Messages')); - - return id(new PHUIListItemView()) - ->setType(PHUIListItemView::TYPE_CUSTOM) - ->setName($message); - } - private function getNoRoomsMenuItem() { $message = phutil_tag( 'div', diff --git a/src/applications/people/controller/PhabricatorPeopleProfileController.php b/src/applications/people/controller/PhabricatorPeopleProfileController.php index 3447525f1a..2067654ff0 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileController.php @@ -64,7 +64,9 @@ final class PhabricatorPeopleProfileController $class = 'PhabricatorConpherenceApplication'; if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { - $href = '/conpherence/new/?participant='.$user->getPHID(); + $href = id(new PhutilURI('/conpherence/new/')) + ->setQueryParam('participant', $user->getPHID()); + $actions->addAction( id(new PhabricatorActionView()) ->setIcon('fa-comments') diff --git a/src/docs/user/installation_guide.diviner b/src/docs/user/installation_guide.diviner index 615ad63fda..4df177540e 100644 --- a/src/docs/user/installation_guide.diviner +++ b/src/docs/user/installation_guide.diviner @@ -167,23 +167,10 @@ If it doesn't show up, add: ..to "/etc/php.d/apc.ini" or the "php.ini" file indicated by "php -i". -= Updating Phabricator = - -Since Phabricator is under active development, you should update frequently. To -update Phabricator: - - - Stop the webserver (including `php-fpm`, if you use it). - - Run `git pull` in `libphutil/`, `arcanist/` and `phabricator/`. - - Run `phabricator/bin/storage upgrade`. - - Restart the webserver (and `php-fpm`, if you stopped it earlier). - -For more details, see @{article:Configuration Guide}. You can use a script -similar to this one to automate the process: - -http://www.phabricator.com/rsrc/install/update_phabricator.sh - = Next Steps = Continue by: - - configuring Phabricator with the @{article:Configuration Guide}. + - configuring Phabricator with the @{article:Configuration Guide}; or + - learning how to keep Phabricator up to date with + @{article:Upgrading Phabricator}. diff --git a/src/docs/user/upgrading.diviner b/src/docs/user/upgrading.diviner new file mode 100644 index 0000000000..e8b7228ade --- /dev/null +++ b/src/docs/user/upgrading.diviner @@ -0,0 +1,130 @@ +@title Upgrading Phabricator +@group intro + +This document contains instructions for keeping Phabricator up to date. + +Overview +======== + +Phabricator is under active development, and new features are released +continuously. Staying up to date will keep your install secure. + +We recommend installs upgrade regularly (every 1-2 weeks). Upgrades usually go +smoothly and complete in a few minutes. If you put off upgrades for a long +time, it may take a lot more work to bring things up to date if you want access +to a useful new feature or an important security change. + + +Staying On Top of Changes +========================= + +We release a weekly [[https://secure.phabricator.com/w/changelog | Changelog]], +which describes changes in the previous week. You can look at the changelogs +for an idea of what new features are available, upcoming changes, security +information, and warnings about compatibility issues or migrations. + + +Stable Branch +============= + +You can either run the `master` or `stable` branch of Phabricator. The `stable` +branch is run in the [[ https://phacility.com | Phacility Cluster ]], and lags +about a week behind `master`. + +The `stable` branch is a little more stable than `master`, and may be helpful +if you administrate a larger install. + +We promote `master` to `stable` about once a week, then publish the changelog +and deploy the cluster. During the week, major bugfixes are cherry-picked to +the `stable` branch. The changelog lists the `stable` hashes for that week, +as well as any fixes which were cherry-picked. + +To switch to `stable`, check the branch out in each working copy: + + phabricator/ $ git checkout stable + arcanist/ $ git checkout stable + libphutil/ $ git checkout stable + +You can now follow the upgrade process normally. + + +Upgrade Process +=============== + +IMPORTANT: You **MUST** restart Apache or PHP-FPM after upgrading. + +Phabricator runs on many different systems, with many different webservers. +Given this diversity, we don't currently maintain a comprehensive upgrade +script which can work on any system. However, the general steps are the same +on every system: + + - Stop the webserver (including `php-fpm`, if you use it). + - Stop the daemons, with `phabricator/bin/phd stop`. + - Run `git pull` in `libphutil/`, `arcanist/` and `phabricator/`. + - Run `phabricator/bin/storage upgrade`. + - Start the daemons, with `phabricator/bin/phd start`. + - Restart the webserver (and `php-fpm`, if you stopped it earlier). + +For some more discussion details, see @{article:Configuration Guide}. + +This template script roughly outlines the steps required to upgrade Phabricator. +You'll need to adjust paths and commands a bit for your particular system: + +```lang=sh +#!/bin/sh + +set -e +set -x + +# This is an example script for updating Phabricator, similar to the one used to +# update . It might not work perfectly on your +# system, but hopefully it should be easy to adapt. This script is not intended +# to work without modifications. + +# NOTE: This script assumes you are running it from a directory which contains +# arcanist/, libphutil/, and phabricator/. + +ROOT=`pwd` # You can hard-code the path here instead. + +### UPDATE WORKING COPIES ###################################################### + +cd $ROOT/libphutil +git pull + +cd $ROOT/arcanist +git pull + +cd $ROOT/phabricator +git pull + + +### CYCLE WEB SERVER AND DAEMONS ############################################### + +# Stop daemons. +$ROOT/phabricator/bin/phd stop + +# If running the notification server, stop it. +# $ROOT/phabricator/bin/aphlict stop + +# Stop the webserver (apache, nginx, lighttpd, etc). This command will differ +# depending on which system and webserver you are running: replace it with an +# appropriate command for your system. +# NOTE: If you're running php-fpm, you should stop it here too. + +sudo /etc/init.d/httpd stop + + +# Upgrade the database schema. You may want to add the "--force" flag to allow +# this script to run noninteractively. +$ROOT/phabricator/bin/storage upgrade + +# Restart the webserver. As above, this depends on your system and webserver. +# NOTE: If you're running php-fpm, restart it here too. +sudo /etc/init.d/httpd start + +# Restart daemons. +$ROOT/phabricator/bin/phd start + +# If running the notification server, start it. +# $ROOT/phabricator/bin/aphlict start +``` diff --git a/webroot/rsrc/js/application/conpherence/behavior-widget-pane.js b/webroot/rsrc/js/application/conpherence/behavior-widget-pane.js index 227db56907..77839e9da0 100644 --- a/webroot/rsrc/js/application/conpherence/behavior-widget-pane.js +++ b/webroot/rsrc/js/application/conpherence/behavior-widget-pane.js @@ -321,6 +321,7 @@ JX.behavior('conpherence-widget-pane', function(config) { }); } }); + threadManager.syncWorkflow(workflow, 'submit'); } ); @@ -331,9 +332,25 @@ JX.behavior('conpherence-widget-pane', function(config) { function (e) { var href = config.widgetBaseUpdateURI + _loadedWidgetsID + '/'; var data = e.getNodeData('remove-person'); - // we end up re-directing to conpherence home + + // While the user is removing themselves, disable the notification + // update behavior. If we don't do this, the user can get an error + // when they remove themselves about permissions as the notification + // code tries to load what jist happened. + var threadManager = JX.ConpherenceThreadManager.getInstance(); + var loadedPhid = threadManager.getLoadedThreadPHID(); + threadManager.setLoadedThreadPHID(null); + new JX.Workflow(href, data) - .start(); + .setCloseHandler(function() { + threadManager.setLoadedThreadPHID(loadedPhid); + }) + // we re-direct to conpherence home so the thread manager will + // fix itself there + .setHandler(function(r) { + JX.$U(r.href).go(); + }) + .start(); } );