diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4245,6 +4245,8 @@ 'PhabricatorProjectProjectPHIDType' => 'applications/project/phid/PhabricatorProjectProjectPHIDType.php', 'PhabricatorProjectQuery' => 'applications/project/query/PhabricatorProjectQuery.php', 'PhabricatorProjectRemoveHeraldAction' => 'applications/project/herald/PhabricatorProjectRemoveHeraldAction.php', + 'PhabricatorProjectReportsController' => 'applications/project/controller/PhabricatorProjectReportsController.php', + 'PhabricatorProjectReportsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectReportsProfileMenuItem.php', 'PhabricatorProjectSchemaSpec' => 'applications/project/storage/PhabricatorProjectSchemaSpec.php', 'PhabricatorProjectSearchEngine' => 'applications/project/query/PhabricatorProjectSearchEngine.php', 'PhabricatorProjectSearchField' => 'applications/project/searchfield/PhabricatorProjectSearchField.php', @@ -10496,6 +10498,8 @@ 'PhabricatorProjectProjectPHIDType' => 'PhabricatorPHIDType', 'PhabricatorProjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorProjectRemoveHeraldAction' => 'PhabricatorProjectHeraldAction', + 'PhabricatorProjectReportsController' => 'PhabricatorProjectController', + 'PhabricatorProjectReportsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorProjectSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorProjectSearchField' => 'PhabricatorSearchTokenizerField', diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php --- a/src/applications/project/application/PhabricatorProjectApplication.php +++ b/src/applications/project/application/PhabricatorProjectApplication.php @@ -71,6 +71,8 @@ => 'PhabricatorProjectBoardViewController', 'move/(?P[1-9]\d*)/' => 'PhabricatorProjectMoveController', 'cover/' => 'PhabricatorProjectCoverController', + 'reports/(?P[1-9]\d*)/' => + 'PhabricatorProjectReportsController', 'board/(?P[1-9]\d*)/' => array( 'edit/(?:(?P\d+)/)?' => 'PhabricatorProjectColumnEditController', diff --git a/src/applications/project/controller/PhabricatorProjectReportsController.php b/src/applications/project/controller/PhabricatorProjectReportsController.php new file mode 100644 --- /dev/null +++ b/src/applications/project/controller/PhabricatorProjectReportsController.php @@ -0,0 +1,96 @@ +getViewer(); + + $response = $this->loadProject(); + if ($response) { + return $response; + } + + $project = $this->getProject(); + $id = $project->getID(); + + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $project, + PhabricatorPolicyCapability::CAN_EDIT); + + $nav = $this->newNavigation( + $project, + PhabricatorProject::ITEM_REPORTS); + + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb(pht('Reports')); + $crumbs->setBorder(true); + + $project_phid = $project->getPHID(); + + $argv = array( + 'sum', + array( + 'accumulate', + array('fact', 'tasks.open-count.create.project', $project_phid), + ), + array( + 'accumulate', + array('fact', 'tasks.open-count.status.project', $project_phid), + ), + array( + 'accumulate', + array('fact', 'tasks.open-count.assign.project', $project_phid), + ), + ); + + $function = id(new PhabricatorComposeChartFunction()) + ->setArguments(array($argv)); + + $datasets = array( + id(new PhabricatorChartDataset()) + ->setFunction($function), + ); + + $chart = id(new PhabricatorFactChart()) + ->setDatasets($datasets); + + $engine = id(new PhabricatorChartEngine()) + ->setViewer($viewer) + ->setChart($chart); + + $chart = $engine->getStoredChart(); + + $panel_type = id(new PhabricatorDashboardChartPanelType()) + ->getPanelTypeKey(); + + $chart_panel = id(new PhabricatorDashboardPanel()) + ->setPanelType($panel_type) + ->setName(pht('%s: Burndown', $project->getName())) + ->setProperty('chartKey', $chart->getChartKey()); + + $chart_view = id(new PhabricatorDashboardPanelRenderingEngine()) + ->setViewer($viewer) + ->setPanel($chart_panel) + ->setParentPanelPHIDs(array()) + ->renderPanel(); + + $view = id(new PHUITwoColumnView()) + ->setFooter( + array( + $chart_view, + )); + + return $this->newPage() + ->setNavigation($nav) + ->setCrumbs($crumbs) + ->setTitle(array($project->getName(), pht('Reports'))) + ->appendChild($view); + } + +} diff --git a/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php b/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php --- a/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php +++ b/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php @@ -37,6 +37,10 @@ ->setBuiltinKey(PhabricatorProject::ITEM_WORKBOARD) ->setMenuItemKey(PhabricatorProjectWorkboardProfileMenuItem::MENUITEMKEY); + $items[] = $this->newItem() + ->setBuiltinKey(PhabricatorProject::ITEM_REPORTS) + ->setMenuItemKey(PhabricatorProjectReportsProfileMenuItem::MENUITEMKEY); + $items[] = $this->newItem() ->setBuiltinKey(PhabricatorProject::ITEM_MEMBERS) ->setMenuItemKey(PhabricatorProjectMembersProfileMenuItem::MENUITEMKEY); diff --git a/src/applications/project/menuitem/PhabricatorProjectReportsProfileMenuItem.php b/src/applications/project/menuitem/PhabricatorProjectReportsProfileMenuItem.php new file mode 100644 --- /dev/null +++ b/src/applications/project/menuitem/PhabricatorProjectReportsProfileMenuItem.php @@ -0,0 +1,80 @@ +getViewer(); + + if (!PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) { + return false; + } + + $class = 'PhabricatorManiphestApplication'; + if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { + return false; + } + + return true; + } + + public function getDisplayName( + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); + + if (strlen($name)) { + return $name; + } + + return $this->getDefaultName(); + } + + public function buildEditEngineFields( + PhabricatorProfileMenuItemConfiguration $config) { + return array( + id(new PhabricatorTextEditField()) + ->setKey('name') + ->setLabel(pht('Name')) + ->setPlaceholder($this->getDefaultName()) + ->setValue($config->getMenuItemProperty('name')), + ); + } + + protected function newMenuItemViewList( + PhabricatorProfileMenuItemConfiguration $config) { + $project = $config->getProfileObject(); + + $id = $project->getID(); + $uri = $project->getReportsURI(); + $name = $this->getDisplayName($config); + + $item = $this->newItemView() + ->setURI($uri) + ->setName($name) + ->setIcon('fa-area-chart'); + + return array( + $item, + ); + } + +} diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -58,6 +58,7 @@ const ITEM_PROFILE = 'project.profile'; const ITEM_POINTS = 'project.points'; const ITEM_WORKBOARD = 'project.workboard'; + const ITEM_REPORTS = 'project.reports'; const ITEM_MEMBERS = 'project.members'; const ITEM_MANAGE = 'project.manage'; const ITEM_MILESTONES = 'project.milestones'; @@ -396,6 +397,10 @@ return urisprintf('/project/board/%d/', $this->getID()); } + public function getReportsURI() { + return urisprintf('/project/reports/%d/', $this->getID()); + } + public function save() { if (!$this->getMailKey()) { $this->setMailKey(Filesystem::readRandomCharacters(20));