From 014bb720505ff8fc8ffa518d77d5e1c3c0a328d8 Mon Sep 17 00:00:00 2001 From: Bob Trahan Date: Tue, 24 Mar 2015 13:04:33 -0700 Subject: [PATCH] Conpherence - add "room" search UI and create UI Summary: Ref T7584. This hits all the major bullets there. Next step on T7584 is figuring out how it integrates into the full UI and column UI. That said, this is a bit buggy feeling right now since Conpherence as is assumes you are a participant all over the place and rooms make no such assumption. I'll probably this bit up next. Test Plan: viewed /conpherence/room/ and saw stuff. viewed the "participant" query as two different users and saw different correct result sets. made a room via the button and it worked. tried to view a room I wasn't a participant in and it failed horribly, which is something to fix in a future diff created a thread via "send message" on a user profile and it worked Reviewers: chad, epriestley Reviewed By: epriestley Subscribers: Korvin, epriestley Maniphest Tasks: T7584 Differential Revision: https://secure.phabricator.com/D12113 --- src/__phutil_library_map__.php | 6 + .../PhabricatorConpherenceApplication.php | 4 + .../controller/ConpherenceController.php | 44 +++-- .../ConpherenceNewRoomController.php | 102 ++++++++++++ .../ConpherenceRoomListController.php | 46 ++++++ .../conpherence/editor/ConpherenceEditor.php | 29 +++- .../query/ConpherenceThreadQuery.php | 44 ++++- .../query/ConpherenceThreadSearchEngine.php | 156 ++++++++++++++++++ .../conpherence/storage/ConpherenceThread.php | 25 ++- .../view/ConpherenceTransactionView.php | 9 +- 10 files changed, 435 insertions(+), 30 deletions(-) create mode 100644 src/applications/conpherence/controller/ConpherenceNewRoomController.php create mode 100644 src/applications/conpherence/controller/ConpherenceRoomListController.php create mode 100644 src/applications/conpherence/query/ConpherenceThreadSearchEngine.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 41fe48eb78..a1d2ac3a54 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -238,6 +238,7 @@ phutil_register_library_map(array( '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', 'ConpherenceParticipantCountQuery' => 'applications/conpherence/query/ConpherenceParticipantCountQuery.php', @@ -247,6 +248,7 @@ phutil_register_library_map(array( 'ConpherenceQueryThreadConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceQueryThreadConduitAPIMethod.php', 'ConpherenceQueryTransactionConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceQueryTransactionConduitAPIMethod.php', 'ConpherenceReplyHandler' => 'applications/conpherence/mail/ConpherenceReplyHandler.php', + 'ConpherenceRoomListController' => 'applications/conpherence/controller/ConpherenceRoomListController.php', 'ConpherenceSchemaSpec' => 'applications/conpherence/storage/ConpherenceSchemaSpec.php', 'ConpherenceSettings' => 'applications/conpherence/constants/ConpherenceSettings.php', 'ConpherenceThread' => 'applications/conpherence/storage/ConpherenceThread.php', @@ -254,6 +256,7 @@ phutil_register_library_map(array( 'ConpherenceThreadListView' => 'applications/conpherence/view/ConpherenceThreadListView.php', 'ConpherenceThreadMailReceiver' => 'applications/conpherence/mail/ConpherenceThreadMailReceiver.php', 'ConpherenceThreadQuery' => 'applications/conpherence/query/ConpherenceThreadQuery.php', + 'ConpherenceThreadSearchEngine' => 'applications/conpherence/query/ConpherenceThreadSearchEngine.php', 'ConpherenceTransaction' => 'applications/conpherence/storage/ConpherenceTransaction.php', 'ConpherenceTransactionComment' => 'applications/conpherence/storage/ConpherenceTransactionComment.php', 'ConpherenceTransactionQuery' => 'applications/conpherence/query/ConpherenceTransactionQuery.php', @@ -3399,6 +3402,7 @@ phutil_register_library_map(array( 'ConpherenceListController' => 'ConpherenceController', 'ConpherenceMenuItemView' => 'AphrontTagView', 'ConpherenceNewController' => 'ConpherenceController', + 'ConpherenceNewRoomController' => 'ConpherenceController', 'ConpherenceNotificationPanelController' => 'ConpherenceController', 'ConpherenceParticipant' => 'ConpherenceDAO', 'ConpherenceParticipantCountQuery' => 'PhabricatorOffsetPagedQuery', @@ -3408,6 +3412,7 @@ phutil_register_library_map(array( 'ConpherenceQueryThreadConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceQueryTransactionConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceReplyHandler' => 'PhabricatorMailReplyHandler', + 'ConpherenceRoomListController' => 'ConpherenceController', 'ConpherenceSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'ConpherenceSettings' => 'ConpherenceConstants', 'ConpherenceThread' => array( @@ -3418,6 +3423,7 @@ phutil_register_library_map(array( 'ConpherenceThreadListView' => 'AphrontView', 'ConpherenceThreadMailReceiver' => 'PhabricatorObjectMailReceiver', 'ConpherenceThreadQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'ConpherenceThreadSearchEngine' => 'PhabricatorApplicationSearchEngine', 'ConpherenceTransaction' => 'PhabricatorApplicationTransaction', 'ConpherenceTransactionComment' => 'PhabricatorApplicationTransactionComment', 'ConpherenceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', diff --git a/src/applications/conpherence/application/PhabricatorConpherenceApplication.php b/src/applications/conpherence/application/PhabricatorConpherenceApplication.php index 3a16c1257f..33cd24e352 100644 --- a/src/applications/conpherence/application/PhabricatorConpherenceApplication.php +++ b/src/applications/conpherence/application/PhabricatorConpherenceApplication.php @@ -36,6 +36,10 @@ final class PhabricatorConpherenceApplication extends PhabricatorApplication { '(?P[1-9]\d*)/' => 'ConpherenceViewController', 'columnview/' => 'ConpherenceColumnViewController', 'new/' => 'ConpherenceNewController', + 'room/' => array( + '(?:query/(?P[^/]+)/)?' => 'ConpherenceRoomListController', + 'new/' => 'ConpherenceNewRoomController', + ), 'panel/' => 'ConpherenceNotificationPanelController', 'widget/(?P[1-9]\d*)/' => 'ConpherenceWidgetController', 'update/(?P[1-9]\d*)/' => 'ConpherenceUpdateController', diff --git a/src/applications/conpherence/controller/ConpherenceController.php b/src/applications/conpherence/controller/ConpherenceController.php index fdccc8d77d..f387c89e8c 100644 --- a/src/applications/conpherence/controller/ConpherenceController.php +++ b/src/applications/conpherence/controller/ConpherenceController.php @@ -39,24 +39,38 @@ abstract class ConpherenceController extends PhabricatorController { } protected function buildApplicationCrumbs() { + return $this->buildConpherenceApplicationCrumbs(); + } + + protected function buildConpherenceApplicationCrumbs($is_rooms = false) { $crumbs = parent::buildApplicationCrumbs(); $crumbs->setBorder(true); - $crumbs - ->addAction( - id(new PHUIListItemView()) - ->setName(pht('New Message')) - ->setHref($this->getApplicationURI('new/')) - ->setIcon('fa-plus-square') - ->setWorkflow(true)) - ->addAction( - id(new PHUIListItemView()) - ->setName(pht('Thread')) - ->setHref('#') - ->setIcon('fa-bars') - ->setStyle('display: none;') - ->addClass('device-widgets-selector') - ->addSigil('device-widgets-selector')); + if ($is_rooms) { + $crumbs + ->addAction( + id(new PHUIListItemView()) + ->setName(pht('New Room')) + ->setHref($this->getApplicationURI('room/new/')) + ->setIcon('fa-plus-square') + ->setWorkflow(true)); + } else { + $crumbs + ->addAction( + id(new PHUIListItemView()) + ->setName(pht('New Message')) + ->setHref($this->getApplicationURI('new/')) + ->setIcon('fa-plus-square') + ->setWorkflow(true)) + ->addAction( + id(new PHUIListItemView()) + ->setName(pht('Thread')) + ->setHref('#') + ->setIcon('fa-bars') + ->setStyle('display: none;') + ->addClass('device-widgets-selector') + ->addSigil('device-widgets-selector')); + } return $crumbs; } diff --git a/src/applications/conpherence/controller/ConpherenceNewRoomController.php b/src/applications/conpherence/controller/ConpherenceNewRoomController.php new file mode 100644 index 0000000000..10f1eeba71 --- /dev/null +++ b/src/applications/conpherence/controller/ConpherenceNewRoomController.php @@ -0,0 +1,102 @@ +getUser(); + + $title = pht('New Room'); + $e_title = true; + $validation_exception = null; + + $conpherence = ConpherenceThread::initializeNewRoom($user); + if ($request->isFormPost()) { + + $xactions = array(); + $xactions[] = id(new ConpherenceTransaction()) + ->setTransactionType(ConpherenceTransactionType::TYPE_PARTICIPANTS) + ->setNewValue(array('+' => array($user->getPHID()))); + $xactions[] = id(new ConpherenceTransaction()) + ->setTransactionType(ConpherenceTransactionType::TYPE_TITLE) + ->setNewValue($request->getStr('title')); + $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')); + + try { + id(new ConpherenceEditor()) + ->setContentSourceFromRequest($request) + ->setContinueOnNoEffect(true) + ->setActor($user) + ->applyTransactions($conpherence, $xactions); + + $uri = $this->getApplicationURI($conpherence->getID()); + return id(new AphrontRedirectResponse()) + ->setURI($uri); + } catch (PhabricatorApplicationTransactionValidationException $ex) { + $validation_exception = $ex; + + $e_title = $ex->getShortMessage(ConpherenceTransactionType::TYPE_TITLE); + + $conpherence->setViewPolicy($request->getStr('viewPolicy')); + $conpherence->setEditPolicy($request->getStr('editPolicy')); + $conpherence->setJoinPolicy($request->getStr('joinPolicy')); + } + } + + $policies = id(new PhabricatorPolicyQuery()) + ->setViewer($user) + ->setObject($conpherence) + ->execute(); + + $submit_uri = $this->getApplicationURI('room/new/'); + $cancel_uri = $this->getApplicationURI('room/'); + + $dialog = $this->newDialog() + ->setWidth(AphrontDialogView::WIDTH_FORM) + ->setValidationException($validation_exception) + ->setUser($user) + ->setTitle($title) + ->addCancelButton($cancel_uri) + ->addSubmitButton(pht('Create Room')); + + $form = id(new PHUIFormLayoutView()) + ->setUser($user) + ->setFullWidth(true) + ->appendChild( + id(new AphrontFormTextControl()) + ->setError($e_title) + ->setLabel(pht('Title')) + ->setName('title') + ->setValue($request->getStr('title'))) + ->appendChild( + id(new AphrontFormPolicyControl()) + ->setName('viewPolicy') + ->setPolicyObject($conpherence) + ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) + ->setPolicies($policies)) + ->appendChild( + id(new AphrontFormPolicyControl()) + ->setName('editPolicy') + ->setPolicyObject($conpherence) + ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) + ->setPolicies($policies)) + ->appendChild( + id(new AphrontFormPolicyControl()) + ->setName('joinPolicy') + ->setPolicyObject($conpherence) + ->setCapability(PhabricatorPolicyCapability::CAN_JOIN) + ->setPolicies($policies)); + + $dialog->appendChild($form); + + return id(new AphrontDialogResponse())->setDialog($dialog); + } + +} diff --git a/src/applications/conpherence/controller/ConpherenceRoomListController.php b/src/applications/conpherence/controller/ConpherenceRoomListController.php new file mode 100644 index 0000000000..04a309d031 --- /dev/null +++ b/src/applications/conpherence/controller/ConpherenceRoomListController.php @@ -0,0 +1,46 @@ +getUser(); + + $controller = id(new PhabricatorApplicationSearchController()) + ->setQueryKey($request->getURIData('queryKey')) + ->setSearchEngine( + id(new ConpherenceThreadSearchEngine()) + ->setIsRooms(true)) + ->setNavigation($this->buildRoomsSideNavView()); + + return $this->delegateToController($controller); + } + + protected function buildApplicationCrumbs() { + return $this->buildConpherenceApplicationCrumbs($is_rooms = true); + } + + public function buildApplicationMenu() { + return $this->buildRoomsSideNavView(true)->getMenu(); + } + + private function buildRoomsSideNavView($for_app = false) { + $user = $this->getRequest()->getUser(); + + $nav = new AphrontSideNavFilterView(); + $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); + + if ($for_app) { + $nav->addFilter('room/new/', pht('Create Room')); + } + + id(new ConpherenceThreadSearchEngine()) + ->setViewer($user) + ->addNavigationItems($nav->getMenu()); + + $nav->selectFilter(null); + + return $nav; + } + + +} diff --git a/src/applications/conpherence/editor/ConpherenceEditor.php b/src/applications/conpherence/editor/ConpherenceEditor.php index 67e66e1c4a..b40bff82d2 100644 --- a/src/applications/conpherence/editor/ConpherenceEditor.php +++ b/src/applications/conpherence/editor/ConpherenceEditor.php @@ -61,6 +61,7 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { ->setTransactionType(ConpherenceTransactionType::TYPE_TITLE) ->setNewValue($title); } + $xactions[] = id(new ConpherenceTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) ->attachComment( @@ -73,7 +74,6 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { ->setContinueOnNoEffect(true) ->setActor($creator) ->applyTransactions($conpherence, $xactions); - } return array($errors, $conpherence); @@ -122,6 +122,9 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { $types[] = ConpherenceTransactionType::TYPE_TITLE; $types[] = ConpherenceTransactionType::TYPE_PARTICIPANTS; $types[] = ConpherenceTransactionType::TYPE_FILES; + $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; + $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; + $types[] = PhabricatorTransactions::TYPE_JOIN_POLICY; return $types; } @@ -483,6 +486,30 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { + case ConpherenceTransactionType::TYPE_TITLE: + if (!$object->getIsRoom() && $this->getIsNewObject()) { + continue; + } + $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.'); + } + $error = new PhabricatorApplicationTransactionValidationError( + $type, + pht('Required'), + $detail, + last($xactions)); + + $error->setIsMissingFieldError(true); + $errors[] = $error; + } + break; case ConpherenceTransactionType::TYPE_PARTICIPANTS: foreach ($xactions as $xaction) { $phids = $this->getPHIDTransactionNewValue( diff --git a/src/applications/conpherence/query/ConpherenceThreadQuery.php b/src/applications/conpherence/query/ConpherenceThreadQuery.php index 12eccbd580..265e7f0327 100644 --- a/src/applications/conpherence/query/ConpherenceThreadQuery.php +++ b/src/applications/conpherence/query/ConpherenceThreadQuery.php @@ -7,6 +7,7 @@ final class ConpherenceThreadQuery private $phids; private $ids; + private $participantPHIDs; private $isRoom; private $needWidgetData; private $needTransactions; @@ -46,6 +47,11 @@ final class ConpherenceThreadQuery return $this; } + public function withParticipantPHIDs(array $phids) { + $this->participantPHIDs = $phids; + return $this; + } + public function withIsRoom($bool) { $this->isRoom = $bool; return $this; @@ -76,8 +82,9 @@ final class ConpherenceThreadQuery $data = queryfx_all( $conn_r, - 'SELECT conpherence_thread.* FROM %T conpherence_thread %Q %Q %Q', + 'SELECT conpherence_thread.* FROM %T conpherence_thread %Q %Q %Q %Q', $table->getTableName(), + $this->buildJoinClause($conn_r), $this->buildWhereClause($conn_r), $this->buildOrderClause($conn_r), $this->buildLimitClause($conn_r)); @@ -106,6 +113,28 @@ final class ConpherenceThreadQuery return $conpherences; } + private function buildGroupClause($conn_r) { + if ($this->participantPHIDs !== null) { + return 'GROUP BY conpherence_thread.id'; + } else { + return $this->buildApplicationSearchGroupClause($conn_r); + } + } + + private function buildJoinClause($conn_r) { + $joins = array(); + + if ($this->participantPHIDs !== null) { + $joins[] = qsprintf( + $conn_r, + 'JOIN %T p ON p.conpherencePHID = conpherence_thread.phid', + id(new ConpherenceParticipant())->getTableName()); + } + + $joins[] = $this->buildApplicationSearchJoinClause($conn_r); + return implode(' ', $joins); + } + protected function buildWhereClause($conn_r) { $where = array(); @@ -114,21 +143,28 @@ final class ConpherenceThreadQuery if ($this->ids !== null) { $where[] = qsprintf( $conn_r, - 'id IN (%Ld)', + 'conpherence_thread.id IN (%Ld)', $this->ids); } if ($this->phids !== null) { $where[] = qsprintf( $conn_r, - 'phid IN (%Ls)', + 'conpherence_thread.phid IN (%Ls)', $this->phids); } + if ($this->participantPHIDs !== null) { + $where[] = qsprintf( + $conn_r, + 'p.participantPHID IN (%Ls)', + $this->participantPHIDs); + } + if ($this->isRoom !== null) { $where[] = qsprintf( $conn_r, - 'isRoom = %d', + 'conpherence_thread.isRoom = %d', (int)$this->isRoom); } diff --git a/src/applications/conpherence/query/ConpherenceThreadSearchEngine.php b/src/applications/conpherence/query/ConpherenceThreadSearchEngine.php new file mode 100644 index 0000000000..f7c3187014 --- /dev/null +++ b/src/applications/conpherence/query/ConpherenceThreadSearchEngine.php @@ -0,0 +1,156 @@ +isRooms = $bool; + return $this; + } + + public function getResultTypeDescription() { + if ($this->isRooms) { + $type = pht('Rooms'); + } else { + $type = pht('Threads'); + } + return $type; + } + + public function getApplicationClassName() { + return 'PhabricatorConpherenceApplication'; + } + + public function buildSavedQueryFromRequest(AphrontRequest $request) { + $saved = new PhabricatorSavedQuery(); + + $saved->setParameter( + 'participantPHIDs', + $this->readUsersFromRequest($request, 'participants')); + + return $saved; + } + + public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { + $query = id(new ConpherenceThreadQuery()) + ->withIsRoom($this->isRooms) + ->needParticipantCache(true); + + $participant_phids = $saved->getParameter('participantPHIDs', array()); + if ($participant_phids && is_array($participant_phids)) { + $query->withParticipantPHIDs($participant_phids); + } + + return $query; + } + + public function buildSearchForm( + AphrontFormView $form, + PhabricatorSavedQuery $saved) { + + $phids = $saved->getParameter('participantPHIDs', array()); + $participant_handles = id(new PhabricatorHandleQuery()) + ->setViewer($this->requireViewer()) + ->withPHIDs($phids) + ->execute(); + $form + ->appendChild( + id(new AphrontFormTokenizerControl()) + ->setDatasource(new PhabricatorPeopleDatasource()) + ->setName('participants') + ->setLabel(pht('Participants')) + ->setValue($participant_handles)); + } + + protected function getURI($path) { + if ($this->isRooms) { + return '/conpherence/room/'.$path; + } else { + // TODO - will need a path if / when "thread" search happens + } + } + + protected function getBuiltinQueryNames() { + $names = array(); + + if ($this->isRooms) { + $names = array( + 'all' => pht('All Rooms'), + ); + + if ($this->requireViewer()->isLoggedIn()) { + $names['participant'] = pht('Participated'); + } + } + + return $names; + } + + public function buildSavedQueryFromBuiltin($query_key) { + + $query = $this->newSavedQuery(); + $query->setQueryKey($query_key); + + switch ($query_key) { + case 'all': + return $query; + case 'participant': + return $query->setParameter( + 'participantPHIDs', + array($this->requireViewer()->getPHID())); + } + + return parent::buildSavedQueryFromBuiltin($query_key); + } + + protected function getRequiredHandlePHIDsForResultList( + array $conpherences, + PhabricatorSavedQuery $query) { + + $recent = mpull($conpherences, 'getRecentParticipantPHIDs'); + return array_unique(array_mergev($recent)); + } + + protected function renderResultList( + array $conpherences, + PhabricatorSavedQuery $query, + array $handles) { + assert_instances_of($conpherences, 'ConpherenceThread'); + + $viewer = $this->requireViewer(); + + $list = new PHUIObjectItemListView(); + $list->setUser($viewer); + foreach ($conpherences as $conpherence) { + $created = phabricator_date($conpherence->getDateCreated(), $viewer); + $data = $conpherence->getDisplayData($viewer); + $title = $data['title']; + + $item = id(new PHUIObjectItemView()) + ->setObjectName($conpherence->getMonogram()) + ->setHeader($title) + ->setHref('/conpherence/'.$conpherence->getID().'/') + ->setObject($conpherence) + ->addIcon('none', $created) + ->addIcon( + 'none', + pht('Messages: %d', $conpherence->getMessageCount())) + ->addAttribute( + array( + id(new PHUIIconView())->setIconFont('fa-envelope-o', 'green'), + ' ', + pht( + 'Last updated %s', + phabricator_datetime($conpherence->getDateModified(), $viewer)), + )); + + $list->addItem($item); + } + + return $list; + } +} diff --git a/src/applications/conpherence/storage/ConpherenceThread.php b/src/applications/conpherence/storage/ConpherenceThread.php index 218e0c5c51..9082a88fbf 100644 --- a/src/applications/conpherence/storage/ConpherenceThread.php +++ b/src/applications/conpherence/storage/ConpherenceThread.php @@ -31,6 +31,8 @@ final class ConpherenceThread extends ConpherenceDAO } public static function initializeNewRoom(PhabricatorUser $creator) { + $participant_phids = array($creator->getPHID()); + return id(new ConpherenceThread()) ->setIsRoom(1) ->setMessageCount(0) @@ -39,7 +41,8 @@ final class ConpherenceThread extends ConpherenceDAO ->attachFilePHIDs(array()) ->setViewPolicy(PhabricatorPolicies::POLICY_USER) ->setEditPolicy($creator->getPHID()) - ->setJoinPolicy(PhabricatorPolicies::POLICY_USER); + ->setJoinPolicy(PhabricatorPolicies::POLICY_USER) + ->setRecentParticipantPHIDs($participant_phids); } protected function getConfiguration() { @@ -79,6 +82,10 @@ final class ConpherenceThread extends ConpherenceDAO return parent::save(); } + public function getMonogram() { + return 'Z'.$this->getID(); + } + public function attachParticipants(array $participants) { assert_instances_of($participants, 'ConpherenceParticipant'); $this->participants = $participants; @@ -91,6 +98,11 @@ final class ConpherenceThread extends ConpherenceDAO $participants = $this->getParticipants(); return $participants[$phid]; } + public function getParticipantIfExists($phid) { + $participants = $this->getParticipants(); + return idx($participants, $phid); + } + public function getParticipantPHIDs() { $participants = $this->getParticipants(); return array_keys($participants); @@ -191,10 +203,13 @@ final class ConpherenceThread extends ConpherenceDAO $final = $count == 3; } - $participants = $this->getParticipants(); - $user_participation = $participants[$user->getPHID()]; - $unread_count = $this->getMessageCount() - - $user_participation->getSeenMessageCount(); + $user_participation = $this->getParticipantIfExists($user->getPHID()); + if ($user_participation) { + $user_seen_count = $user_participation->getSeenMessageCount(); + } else { + $user_seen_count = 0; + } + $unread_count = $this->getMessageCount() - $user_seen_count; return array( 'title' => $title, diff --git a/src/applications/conpherence/view/ConpherenceTransactionView.php b/src/applications/conpherence/view/ConpherenceTransactionView.php index 2e070f92d7..ab2ac03a94 100644 --- a/src/applications/conpherence/view/ConpherenceTransactionView.php +++ b/src/applications/conpherence/view/ConpherenceTransactionView.php @@ -89,15 +89,14 @@ final class ConpherenceTransactionView extends AphrontView { $content_class = null; $content = null; switch ($transaction->getTransactionType()) { - case ConpherenceTransactionType::TYPE_TITLE: - $content = $transaction->getTitle(); - $transaction_view->addClass('conpherence-edited'); - $transaction_view->addClass('grouped'); - break; case ConpherenceTransactionType::TYPE_FILES: $content = $transaction->getTitle(); break; + case ConpherenceTransactionType::TYPE_TITLE: case ConpherenceTransactionType::TYPE_PARTICIPANTS: + case PhabricatorTransactions::TYPE_VIEW_POLICY: + case PhabricatorTransactions::TYPE_EDIT_POLICY: + case PhabricatorTransactions::TYPE_JOIN_POLICY: $content = $transaction->getTitle(); $transaction_view->addClass('conpherence-edited'); $transaction_view->addClass('grouped');