private function buildTagListTable(DiffusionRequest $drequest) { $tag_limit = 15; $query = DiffusionTagListQuery::newFromDiffusionRequest($drequest); $query->setLimit($tag_limit + 1); $tags = $query->loadTags(); if (!$tags) { return null; } $more_tags = count($tags) > $tag_limit; $tags = array_slice($tags, 0, $tag_limit); $commits = id(new PhabricatorAuditCommitQuery())->withIdentifiers($drequest->getRepository()->getID(), mpull($tags, 'getCommitIdentifier'))->needCommitData(true)->execute(); $view = new DiffusionTagListView(); $view->setDiffusionRequest($drequest); $view->setTags($tags); $view->setUser($this->getRequest()->getUser()); $view->setCommits($commits); $phids = $view->getRequiredHandlePHIDs(); $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); $view->setHandles($handles); $panel = new AphrontPanelView(); $panel->setHeader('Tags'); if ($more_tags) { $panel->setCaption('Showing the ' . $tag_limit . ' most recent tags.'); } $panel->addButton(phutil_render_tag('a', array('href' => $drequest->generateURI(array('action' => 'tags')), 'class' => 'grey button'), "Show All Tags »")); $panel->appendChild($view); return $panel; }
public function renderBurn() { $request = $this->getRequest(); $user = $request->getUser(); $handle = null; $project_phid = $request->getStr('project'); if ($project_phid) { $phids = array($project_phid); $handles = $this->loadViewerHandles($phids); $handle = $handles[$project_phid]; } $table = new ManiphestTransaction(); $conn = $table->establishConnection('r'); $joins = ''; if ($project_phid) { $joins = qsprintf($conn, 'JOIN %T t ON x.taskID = t.id JOIN %T p ON p.taskPHID = t.phid AND p.projectPHID = %s', id(new ManiphestTask())->getTableName(), id(new ManiphestTaskProject())->getTableName(), $project_phid); } $data = queryfx_all($conn, 'SELECT x.oldValue, x.newValue, x.dateCreated FROM %T x %Q WHERE transactionType = %s ORDER BY x.dateCreated ASC', $table->getTableName(), $joins, ManiphestTransactionType::TYPE_STATUS); $stats = array(); $day_buckets = array(); $open_tasks = array(); foreach ($data as $key => $row) { // NOTE: Hack to avoid json_decode(). $oldv = trim($row['oldValue'], '"'); $newv = trim($row['newValue'], '"'); $old_is_open = $oldv === (string) ManiphestTaskStatus::STATUS_OPEN; $new_is_open = $newv === (string) ManiphestTaskStatus::STATUS_OPEN; $is_open = $new_is_open && !$old_is_open; $is_close = $old_is_open && !$new_is_open; $data[$key]['_is_open'] = $is_open; $data[$key]['_is_close'] = $is_close; if (!$is_open && !$is_close) { // This is either some kind of bogus event, or a resolution change // (e.g., resolved -> invalid). Just skip it. continue; } $day_bucket = phabricator_format_local_time($row['dateCreated'], $user, 'Yz'); $day_buckets[$day_bucket] = $row['dateCreated']; if (empty($stats[$day_bucket])) { $stats[$day_bucket] = array('open' => 0, 'close' => 0); } $stats[$day_bucket][$is_close ? 'close' : 'open']++; } $template = array('open' => 0, 'close' => 0); $rows = array(); $rowc = array(); $last_month = null; $last_month_epoch = null; $last_week = null; $last_week_epoch = null; $week = null; $month = null; $last = last_key($stats) - 1; $period = $template; foreach ($stats as $bucket => $info) { $epoch = $day_buckets[$bucket]; $week_bucket = phabricator_format_local_time($epoch, $user, 'YW'); if ($week_bucket != $last_week) { if ($week) { $rows[] = $this->formatBurnRow('Week of ' . phabricator_date($last_week_epoch, $user), $week); $rowc[] = 'week'; } $week = $template; $last_week = $week_bucket; $last_week_epoch = $epoch; } $month_bucket = phabricator_format_local_time($epoch, $user, 'Ym'); if ($month_bucket != $last_month) { if ($month) { $rows[] = $this->formatBurnRow(phabricator_format_local_time($last_month_epoch, $user, 'F, Y'), $month); $rowc[] = 'month'; } $month = $template; $last_month = $month_bucket; $last_month_epoch = $epoch; } $rows[] = $this->formatBurnRow(phabricator_date($epoch, $user), $info); $rowc[] = null; $week['open'] += $info['open']; $week['close'] += $info['close']; $month['open'] += $info['open']; $month['close'] += $info['close']; $period['open'] += $info['open']; $period['close'] += $info['close']; } if ($week) { $rows[] = $this->formatBurnRow('Week To Date', $week); $rowc[] = 'week'; } if ($month) { $rows[] = $this->formatBurnRow('Month To Date', $month); $rowc[] = 'month'; } $rows[] = $this->formatBurnRow('All Time', $period); $rowc[] = 'aggregate'; $rows = array_reverse($rows); $rowc = array_reverse($rowc); $table = new AphrontTableView($rows); $table->setRowClasses($rowc); $table->setHeaders(array('Period', 'Opened', 'Closed', 'Change')); $table->setColumnClasses(array('right wide', 'n', 'n', 'n')); if ($handle) { $header = "Task Burn Rate for Project " . $handle->renderLink(); $caption = "<p>NOTE: This table reflects tasks <em>currently</em> in " . "the project. If a task was opened in the past but added to " . "the project recently, it is counted on the day it was " . "opened, not the day it was categorized. If a task was part " . "of this project in the past but no longer is, it is not " . "counted at all.</p>"; } else { $header = "Task Burn Rate for All Tasks"; $caption = null; } $panel = new AphrontPanelView(); $panel->setHeader($header); $panel->setCaption($caption); $panel->appendChild($table); $tokens = array(); if ($handle) { $tokens = array($handle->getPHID() => $handle->getFullName()); } $filter = $this->renderReportFilters($tokens, $has_window = false); $id = celerity_generate_unique_node_id(); $chart = phutil_render_tag('div', array('id' => $id, 'style' => 'border: 1px solid #6f6f6f; ' . 'margin: 1em 2em; ' . 'height: 400px; '), ''); list($burn_x, $burn_y) = $this->buildSeries($data); require_celerity_resource('raphael-core'); require_celerity_resource('raphael-g'); require_celerity_resource('raphael-g-line'); Javelin::initBehavior('line-chart', array('hardpoint' => $id, 'x' => array($burn_x), 'y' => array($burn_y), 'xformat' => 'epoch')); return array($filter, $chart, $panel); }
public function processRequest() { $request = $this->getRequest(); $uri = $request->getStr('uri'); $id = $request->getStr('id'); $repositories = id(new PhabricatorRepository())->loadAll(); if ($uri) { $uri_path = id(new PhutilURI($uri))->getPath(); $matches = array(); // Try to figure out which tracked repository this external lives in by // comparing repository metadata. We look for an exact match, but accept // a partial match. foreach ($repositories as $key => $repository) { $remote_uri = new PhutilURI($repository->getRemoteURI()); if ($remote_uri->getPath() == $uri_path) { $matches[$key] = 1; } if ($repository->getPublicRemoteURI() == $uri) { $matches[$key] = 2; } if ($repository->getRemoteURI() == $uri) { $matches[$key] = 3; } } arsort($matches); $best_match = head_key($matches); if ($best_match) { $repository = $repositories[$best_match]; $redirect = DiffusionRequest::generateDiffusionURI(array('action' => 'browse', 'callsign' => $repository->getCallsign(), 'branch' => $repository->getDefaultBranch(), 'commit' => $id)); return id(new AphrontRedirectResponse())->setURI($redirect); } } // TODO: This is a rare query but does a table scan, add a key? $commits = id(new PhabricatorRepositoryCommit())->loadAllWhere('commitIdentifier = %s', $id); if (empty($commits)) { $desc = null; if ($uri) { $desc = phutil_escape_html($uri) . ', at '; } $desc .= phutil_escape_html($id); $content = id(new AphrontErrorView())->setTitle('Unknown External')->setSeverity(AphrontErrorView::SEVERITY_WARNING)->appendChild("<p>This external ({$desc}) does not appear in any tracked " . "repository. It may exist in an untracked repository that " . "Diffusion does not know about.</p>"); } else { if (count($commits) == 1) { $commit = head($commits); $repo = $repositories[$commit->getRepositoryID()]; $redirect = DiffusionRequest::generateDiffusionURI(array('action' => 'browse', 'callsign' => $repo->getCallsign(), 'branch' => $repo->getDefaultBranch(), 'commit' => $commit->getCommitIdentifier())); return id(new AphrontRedirectResponse())->setURI($redirect); } else { $rows = array(); foreach ($commits as $commit) { $repo = $repositories[$commit->getRepositoryID()]; $href = DiffusionRequest::generateDiffusionURI(array('action' => 'browse', 'callsign' => $repo->getCallsign(), 'branch' => $repo->getDefaultBranch(), 'commit' => $commit->getCommitIdentifier())); $rows[] = array(phutil_render_tag('a', array('href' => $href), phutil_escape_html('r' . $repo->getCallsign() . $commit->getCommitIdentifier())), phutil_escape_html($commit->loadCommitData()->getSummary())); } $table = new AphrontTableView($rows); $table->setHeaders(array('Commit', 'Description')); $table->setColumnClasses(array('pri', 'wide')); $content = new AphrontPanelView(); $content->setHeader('Multiple Matching Commits'); $content->setCaption('This external reference matches multiple known commits.'); $content->appendChild($table); } } return $this->buildStandardPageResponse($content, array('title' => 'Unresolvable External')); }
public function buildCommitPanel() { $request = $this->getRequest(); $user = $request->getUser(); $phids = array($user->getPHID()); $query = new PhabricatorAuditCommitQuery(); $query->withAuthorPHIDs($phids); $query->withStatus(PhabricatorAuditQuery::STATUS_OPEN); $query->needCommitData(true); $query->setLimit(10); $commits = $query->execute(); if (!$commits) { return $this->renderMinipanel('No Problem Commits', 'No one has raised concerns with your commits.'); } $view = new PhabricatorAuditCommitListView(); $view->setCommits($commits); $view->setUser($user); $phids = $view->getRequiredHandlePHIDs(); $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); $view->setHandles($handles); $panel = new AphrontPanelView(); $panel->setHeader('Problem Commits'); $panel->setCaption('Commits which auditors have raised concerns about.'); $panel->appendChild($view); $panel->addButton(phutil_render_tag('a', array('href' => '/audit/', 'class' => 'button grey'), "View Problem Commits »")); return $panel; }
private function renderUploadPanel() { $request = $this->getRequest(); $user = $request->getUser(); $limit_text = PhabricatorFileUploadView::renderUploadLimit(); if ($this->useBasicUploader()) { $upload_panel = new PhabricatorFileUploadView(); $upload_panel->setUser($user); } else { require_celerity_resource('files-css'); $upload_id = celerity_generate_unique_node_id(); $panel_id = celerity_generate_unique_node_id(); $upload_panel = new AphrontPanelView(); $upload_panel->setHeader('Upload Files'); $upload_panel->setCaption($limit_text); $upload_panel->setCreateButton('Basic Uploader', $request->getRequestURI()->setQueryParam('basic_uploader', true)); $upload_panel->setWidth(AphrontPanelView::WIDTH_FULL); $upload_panel->setID($panel_id); $upload_panel->appendChild(phutil_render_tag('div', array('id' => $upload_id, 'style' => 'display: none;', 'class' => 'files-drag-and-drop'), '')); Javelin::initBehavior('files-drag-and-drop', array('uri' => '/file/dropupload/', 'browseURI' => '/file/filter/my/', 'control' => $upload_id, 'target' => $panel_id, 'activatedClass' => 'aphront-panel-view-drag-and-drop')); } return $upload_panel; }
private function buildMergesTable(PhabricatorRepositoryCommit $commit) { $drequest = $this->getDiffusionRequest(); $limit = 50; $merge_query = DiffusionMergedCommitsQuery::newFromDiffusionRequest($drequest); $merge_query->setLimit($limit + 1); $merges = $merge_query->loadMergedCommits(); if (!$merges) { return null; } $caption = null; if (count($merges) > $limit) { $merges = array_slice($merges, 0, $limit); $caption = "This commit merges more than {$limit} changes. Only the first " . "{$limit} are shown."; } $history_table = new DiffusionHistoryTableView(); $history_table->setDiffusionRequest($drequest); $history_table->setHistory($merges); $phids = $history_table->getRequiredHandlePHIDs(); $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); $history_table->setHandles($handles); $panel = new AphrontPanelView(); $panel->setHeader('Merged Changes'); $panel->setCaption($caption); $panel->appendChild($history_table); return $panel; }
private function buildMergesTable(PhabricatorRepositoryCommit $commit) { $drequest = $this->getDiffusionRequest(); $limit = 50; $merges = array(); try { $merges = $this->callConduitWithDiffusionRequest('diffusion.mergedcommitsquery', array('commit' => $drequest->getCommit(), 'limit' => $limit + 1)); } catch (ConduitException $ex) { if ($ex->getMessage() != 'ERR-UNSUPPORTED-VCS') { throw $ex; } } if (!$merges) { return null; } $caption = null; if (count($merges) > $limit) { $merges = array_slice($merges, 0, $limit); $caption = "This commit merges more than {$limit} changes. Only the first " . "{$limit} are shown."; } $history_table = new DiffusionHistoryTableView(); $history_table->setUser($this->getRequest()->getUser()); $history_table->setDiffusionRequest($drequest); $history_table->setHistory($merges); $history_table->loadRevisions(); $phids = $history_table->getRequiredHandlePHIDs(); $handles = $this->loadViewerHandles($phids); $history_table->setHandles($handles); $panel = new AphrontPanelView(); $panel->setHeader(pht('Merged Changes')); $panel->setCaption($caption); $panel->appendChild($history_table); $panel->setNoBackground(); return $panel; }