diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index d47aa5cfe4..601fa67e89 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -293,6 +293,7 @@ phutil_register_library_map(array( 'DiffusionView' => 'applications/diffusion/view/base', 'HeraldAction' => 'applications/herald/storage/action', 'HeraldActionConfig' => 'applications/herald/config/action', + 'HeraldAllRulesController' => 'applications/herald/controller/all', 'HeraldApplyTranscript' => 'applications/herald/storage/transcript/apply', 'HeraldCommitAdapter' => 'applications/herald/adapter/commit', 'HeraldCondition' => 'applications/herald/storage/condition', @@ -317,6 +318,7 @@ phutil_register_library_map(array( 'HeraldRepetitionPolicyConfig' => 'applications/herald/config/repetitionpolicy', 'HeraldRule' => 'applications/herald/storage/rule', 'HeraldRuleController' => 'applications/herald/controller/rule', + 'HeraldRuleListView' => 'applications/herald/view/rulelist', 'HeraldRuleTranscript' => 'applications/herald/storage/transcript/rule', 'HeraldTestConsoleController' => 'applications/herald/controller/test', 'HeraldTranscript' => 'applications/herald/storage/transcript/base', @@ -974,6 +976,7 @@ phutil_register_library_map(array( 'DiffusionSymbolController' => 'DiffusionController', 'DiffusionView' => 'AphrontView', 'HeraldAction' => 'HeraldDAO', + 'HeraldAllRulesController' => 'HeraldController', 'HeraldApplyTranscript' => 'HeraldDAO', 'HeraldCommitAdapter' => 'HeraldObjectAdapter', 'HeraldCondition' => 'HeraldDAO', @@ -986,6 +989,7 @@ phutil_register_library_map(array( 'HeraldNewController' => 'HeraldController', 'HeraldRule' => 'HeraldDAO', 'HeraldRuleController' => 'HeraldController', + 'HeraldRuleListView' => 'AphrontView', 'HeraldTestConsoleController' => 'HeraldController', 'HeraldTranscript' => 'HeraldDAO', 'HeraldTranscriptController' => 'HeraldController', diff --git a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php index b73dfefd99..e60334c913 100644 --- a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php +++ b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php @@ -274,6 +274,10 @@ class AphrontDefaultApplicationConfiguration 'rule/(?:(?P\d+)/)?$' => 'HeraldRuleController', 'delete/(?P\d+)/$' => 'HeraldDeleteController', 'test/$' => 'HeraldTestConsoleController', + 'all/' => array( + '$' => 'HeraldAllRulesController', + 'view/(?P[^/]+)/$' => 'HeraldAllRulesController', + ), 'transcript/$' => 'HeraldTranscriptListController', 'transcript/(?P\d+)/(?:(?P\w+)/)?$' => 'HeraldTranscriptController', diff --git a/src/applications/herald/controller/all/HeraldAllRulesController.php b/src/applications/herald/controller/all/HeraldAllRulesController.php new file mode 100644 index 0000000000..f78ea70ab0 --- /dev/null +++ b/src/applications/herald/controller/all/HeraldAllRulesController.php @@ -0,0 +1,158 @@ +view = idx($data, 'view'); + } + + public function processRequest() { + + $request = $this->getRequest(); + $user = $request->getUser(); + $this->viewPHID = nonempty($request->getStr('phid'), null); + + if ($request->isFormPost()) { + $phid_arr = $request->getArr('view_user'); + $view_target = head($phid_arr); + return id(new AphrontRedirectResponse()) + ->setURI($request->getRequestURI()->alter('phid', $view_target)); + } + + $map = HeraldContentTypeConfig::getContentTypeMap(); + if (empty($map[$this->view])) { + reset($map); + $this->view = key($map); + } + + $offset = $request->getInt('offset', 0); + $pager = new AphrontPagerView(); + $pager->setPageSize(50); + $pager->setOffset($offset); + $pager->setURI($request->getRequestURI(), 'offset'); + + list($rules, $handles) = $this->queryRules($pager); + + if (!$this->viewPHID) { + $view_users = array(); + } else { + $view_users = array( + $this->viewPHID => $handles[$this->viewPHID]->getFullName(), + ); + } + + $filter_form = id(new AphrontFormView()) + ->setUser($user) + ->appendChild( + id(new AphrontFormTokenizerControl()) + ->setDatasource('/typeahead/common/users/') + ->setLabel('View User') + ->setName('view_user') + ->setValue($view_users) + ->setLimit(1)); + $filter_view = new AphrontListFilterView(); + $filter_view->appendChild($filter_form); + + $list_view = id(new HeraldRuleListView()) + ->setRules($rules) + ->setHandles($handles) + ->setMap($map) + ->setAllowCreation(false) + ->setView($this->view); + $panel = $list_view->render(); + $panel->appendChild($pager); + + $sidenav = new AphrontSideNavView(); + $sidenav->appendChild($filter_view); + $sidenav->appendChild($panel); + + $query = ''; + if ($this->viewPHID) { + $query = '?phid='.$this->viewPHID; + } + + foreach ($map as $key => $value) { + $sidenav->addNavItem( + phutil_render_tag( + 'a', + array( + 'href' => '/herald/all/view/'.$key.'/'.$query, + 'class' => ($key == $this->view) + ? 'aphront-side-nav-selected' + : null, + ), + phutil_escape_html($value))); + } + + return $this->buildStandardPageResponse( + $sidenav, + array( + 'title' => 'Herald', + 'tab' => 'all', + )); + } + + private function queryRules(AphrontPagerView $pager) { + $rule = new HeraldRule(); + $conn_r = $rule->establishConnection('r'); + + $where_clause = qsprintf( + $conn_r, + 'WHERE contentType = %s', + $this->view); + + if ($this->viewPHID) { + $where_clause .= qsprintf( + $conn_r, + ' AND authorPHID = %s', + $this->viewPHID); + } + + $data = queryfx_all( + $conn_r, + 'SELECT * FROM %T + %Q + ORDER BY id DESC + LIMIT %d, %d', + $rule->getTableName(), + $where_clause, + $pager->getOffset(), + $pager->getPageSize() + 1); + $data = $pager->sliceResults($data); + $rules = $rule->loadAllFromArray($data); + + $need_phids = mpull($rules, 'getAuthorPHID'); + if ($this->viewPHID) { + $need_phids[] = $this->viewPHID; + } + + $handles = id(new PhabricatorObjectHandleData($need_phids)) + ->loadHandles(); + + return array($rules, $handles); + } +} + diff --git a/src/applications/herald/controller/all/__init__.php b/src/applications/herald/controller/all/__init__.php new file mode 100644 index 0000000000..a0f8c85f22 --- /dev/null +++ b/src/applications/herald/controller/all/__init__.php @@ -0,0 +1,27 @@ +setTabs( - array( - 'rules' => array( - 'href' => '/herald/', - 'name' => 'Rules', - ), - 'test' => array( - 'href' => '/herald/test/', - 'name' => 'Test Console', - ), - 'transcripts' => array( - 'href' => '/herald/transcript/', - 'name' => 'Transcripts', - ), - 'help' => array( - 'href' => $doclink, - 'name' => 'Help', - ), + $tabs = array( + 'rules' => array( + 'href' => '/herald/', + 'name' => 'Rules', ), + 'test' => array( + 'href' => '/herald/test/', + 'name' => 'Test Console', + ), + 'transcripts' => array( + 'href' => '/herald/transcript/', + 'name' => 'Transcripts', + ), + 'help' => array( + 'href' => $doclink, + 'name' => 'Help', + ), + ); + + $user = $this->getRequest()->getUser(); + if ($user->getIsAdmin()) { + $tabs['all'] = array( + 'href' => '/herald/all', + 'name' => 'All Rules', + ); + } + + $page->setTabs( + $tabs, idx($data, 'tab')); $response = new AphrontWebpageResponse(); diff --git a/src/applications/herald/controller/delete/HeraldDeleteController.php b/src/applications/herald/controller/delete/HeraldDeleteController.php index a4cbc4f131..291aed4196 100644 --- a/src/applications/herald/controller/delete/HeraldDeleteController.php +++ b/src/applications/herald/controller/delete/HeraldDeleteController.php @@ -34,7 +34,7 @@ class HeraldDeleteController extends HeraldController { $request = $this->getRequest(); $user = $request->getUser(); - if ($user->getPHID() != $rule->getAuthorPHID()) { + if ($user->getPHID() != $rule->getAuthorPHID() && !$user->getIsAdmin()) { return new Aphront400Response(); } diff --git a/src/applications/herald/controller/home/HeraldHomeController.php b/src/applications/herald/controller/home/HeraldHomeController.php index 661f975f85..0a8293d552 100644 --- a/src/applications/herald/controller/home/HeraldHomeController.php +++ b/src/applications/herald/controller/home/HeraldHomeController.php @@ -44,64 +44,13 @@ class HeraldHomeController extends HeraldController { $handles = id(new PhabricatorObjectHandleData($need_phids)) ->loadHandles(); - $type = 'differential'; - - $rows = array(); - foreach ($rules as $rule) { - $owner = $handles[$rule->getAuthorPHID()]->renderLink(); - - $name = phutil_render_tag( - 'a', - array( - 'href' => '/herald/rule/'.$rule->getID().'/', - ), - phutil_escape_html($rule->getName())); - - $delete = 'delete'; - $delete = javelin_render_tag( - 'a', - array( - 'href' => '/herald/delete/'.$rule->getID().'/', - 'sigil' => 'workflow', - 'class' => 'button small grey', - ), - 'Delete'); - - $rows[] = array( - $map[$rule->getContentType()], - $owner, - $name, - $delete, - ); - } - - $rules_for = phutil_escape_html($map[$this->view]); - - $table = new AphrontTableView($rows); - $table->setNoDataString( - "No matching subscription rules for {$rules_for}."); - - $table->setHeaders( - array( - 'Type', - 'Owner', - 'Rule Name', - '', - )); - $table->setColumnClasses( - array( - '', - '', - 'wide wrap pri', - 'action' - )); - - $panel = new AphrontPanelView(); - $panel->setHeader("Herald Rules for {$rules_for}"); - $panel->setCreateButton( - 'Create New Herald Rule', - '/herald/new/'.$this->view.'/'); - $panel->appendChild($table); + $list_view = id(new HeraldRuleListView()) + ->setRules($rules) + ->setHandles($handles) + ->setMap($map) + ->setAllowCreation(true) + ->setView($this->view); + $panel = $list_view->render(); $sidenav = new AphrontSideNavView(); $sidenav->appendChild($panel); diff --git a/src/applications/herald/controller/home/__init__.php b/src/applications/herald/controller/home/__init__.php index f72d87f3cf..336ecb982f 100644 --- a/src/applications/herald/controller/home/__init__.php +++ b/src/applications/herald/controller/home/__init__.php @@ -9,10 +9,8 @@ phutil_require_module('phabricator', 'applications/herald/config/contenttype'); phutil_require_module('phabricator', 'applications/herald/controller/base'); phutil_require_module('phabricator', 'applications/herald/storage/rule'); +phutil_require_module('phabricator', 'applications/herald/view/rulelist'); phutil_require_module('phabricator', 'applications/phid/handle/data'); -phutil_require_module('phabricator', 'infrastructure/javelin/markup'); -phutil_require_module('phabricator', 'view/control/table'); -phutil_require_module('phabricator', 'view/layout/panel'); phutil_require_module('phabricator', 'view/layout/sidenav'); phutil_require_module('phutil', 'markup'); diff --git a/src/applications/herald/controller/rule/HeraldRuleController.php b/src/applications/herald/controller/rule/HeraldRuleController.php index cb0c997513..789e5d478b 100644 --- a/src/applications/herald/controller/rule/HeraldRuleController.php +++ b/src/applications/herald/controller/rule/HeraldRuleController.php @@ -36,7 +36,7 @@ class HeraldRuleController extends HeraldController { if (!$rule) { return new Aphront404Response(); } - if ($rule->getAuthorPHID() != $user->getPHID()) { + if ($rule->getAuthorPHID() != $user->getPHID() && !$user->getIsAdmin()) { throw new Exception("You don't own this rule and can't edit it."); } } else { diff --git a/src/applications/herald/view/rulelist/HeraldRuleListView.php b/src/applications/herald/view/rulelist/HeraldRuleListView.php new file mode 100644 index 0000000000..832734c45e --- /dev/null +++ b/src/applications/herald/view/rulelist/HeraldRuleListView.php @@ -0,0 +1,115 @@ +rules = $rules; + return $this; + } + + public function setHandles(array $handles) { + $this->handles = $handles; + return $this; + } + + public function setMap($map) { + $this->map = $map; + return $this; + } + + public function setView($view) { + $this->view = $view; + return $this; + } + + public function setAllowCreation($allow_creation) { + $this->allowCreation = $allow_creation; + return $this; + } + + public function render() { + $rows = array(); + foreach ($this->rules as $rule) { + $owner = $this->handles[$rule->getAuthorPHID()]->renderLink(); + + $name = phutil_render_tag( + 'a', + array( + 'href' => '/herald/rule/'.$rule->getID().'/', + ), + phutil_escape_html($rule->getName())); + + $delete = javelin_render_tag( + 'a', + array( + 'href' => '/herald/delete/'.$rule->getID().'/', + 'sigil' => 'workflow', + 'class' => 'button small grey', + ), + 'Delete'); + + $rows[] = array( + $this->map[$rule->getContentType()], + $owner, + $name, + $delete, + ); + } + + $rules_for = phutil_escape_html($this->map[$this->view]); + + $table = new AphrontTableView($rows); + $table->setNoDataString( + "No matching subscription rules for {$rules_for}."); + + $table->setHeaders( + array( + 'Type', + 'Owner', + 'Rule Name', + '', + )); + $table->setColumnClasses( + array( + '', + '', + 'wide wrap pri', + 'action' + )); + + $panel = new AphrontPanelView(); + $panel->setHeader("Herald Rules for {$rules_for}"); + + if ($this->allowCreation) { + $panel->setCreateButton( + 'Create New Herald Rule', + '/herald/new/'.$this->view.'/'); + } + + $panel->appendChild($table); + + return $panel; + + } +} diff --git a/src/applications/herald/view/rulelist/__init__.php b/src/applications/herald/view/rulelist/__init__.php new file mode 100644 index 0000000000..a50f4a2beb --- /dev/null +++ b/src/applications/herald/view/rulelist/__init__.php @@ -0,0 +1,17 @@ +