public function processRequest(AphrontRequest $request) { $user = $this->getUser(); $viewer = $request->getUser(); $keys = id(new PhabricatorAuthSSHKeyQuery())->setViewer($viewer)->withObjectPHIDs(array($user->getPHID()))->execute(); $table = id(new PhabricatorAuthSSHKeyTableView())->setUser($viewer)->setKeys($keys)->setCanEdit(true)->setNoDataString(pht("You haven't added any SSH Public Keys.")); $panel = new PHUIObjectBoxView(); $header = new PHUIHeaderView(); $upload_icon = id(new PHUIIconView())->setIconFont('fa-upload'); $upload_button = id(new PHUIButtonView())->setText(pht('Upload Public Key'))->setHref('/auth/sshkey/upload/?objectPHID=' . $user->getPHID())->setWorkflow(true)->setTag('a')->setIcon($upload_icon); try { PhabricatorSSHKeyGenerator::assertCanGenerateKeypair(); $can_generate = true; } catch (Exception $ex) { $can_generate = false; } $generate_icon = id(new PHUIIconView())->setIconFont('fa-lock'); $generate_button = id(new PHUIButtonView())->setText(pht('Generate Keypair'))->setHref('/auth/sshkey/generate/?objectPHID=' . $user->getPHID())->setTag('a')->setWorkflow(true)->setDisabled(!$can_generate)->setIcon($generate_icon); $header->setHeader(pht('SSH Public Keys')); $header->addActionLink($generate_button); $header->addActionLink($upload_button); $panel->setHeader($header); $panel->setTable($table); return $panel; }
public function processRequest(AphrontRequest $request) { if ($request->getExists('new')) { return $this->processNew($request); } if ($request->getExists('edit')) { return $this->processEdit($request); } if ($request->getExists('delete')) { return $this->processDelete($request); } $user = $this->getUser(); $viewer = $request->getUser(); $factors = id(new PhabricatorAuthFactorConfig())->loadAllWhere('userPHID = %s', $user->getPHID()); $rows = array(); $rowc = array(); $highlight_id = $request->getInt('id'); foreach ($factors as $factor) { $impl = $factor->getImplementation(); if ($impl) { $type = $impl->getFactorName(); } else { $type = $factor->getFactorKey(); } if ($factor->getID() == $highlight_id) { $rowc[] = 'highlighted'; } else { $rowc[] = null; } $rows[] = array(javelin_tag('a', array('href' => $this->getPanelURI('?edit=' . $factor->getID()), 'sigil' => 'workflow'), $factor->getFactorName()), $type, phabricator_datetime($factor->getDateCreated(), $viewer), javelin_tag('a', array('href' => $this->getPanelURI('?delete=' . $factor->getID()), 'sigil' => 'workflow', 'class' => 'small grey button'), pht('Remove'))); } $table = new AphrontTableView($rows); $table->setNoDataString(pht("You haven't added any authentication factors to your account yet.")); $table->setHeaders(array(pht('Name'), pht('Type'), pht('Created'), '')); $table->setColumnClasses(array('wide pri', '', 'right', 'action')); $table->setRowClasses($rowc); $table->setDeviceVisibility(array(true, false, false, true)); $panel = new PHUIObjectBoxView(); $header = new PHUIHeaderView(); $help_uri = PhabricatorEnv::getDoclink('User Guide: Multi-Factor Authentication'); $help_icon = id(new PHUIIconView())->setIconFont('fa-info-circle'); $help_button = id(new PHUIButtonView())->setText(pht('Help'))->setHref($help_uri)->setTag('a')->setIcon($help_icon); $create_icon = id(new PHUIIconView())->setIconFont('fa-plus'); $create_button = id(new PHUIButtonView())->setText(pht('Add Authentication Factor'))->setHref($this->getPanelURI('?new=true'))->setTag('a')->setWorkflow(true)->setIcon($create_icon); $header->setHeader(pht('Authentication Factors')); $header->addActionLink($help_button); $header->addActionLink($create_button); $panel->setHeader($header); $panel->setTable($table); return $panel; }
public function handleRequest(AphrontRequest $request) { $viewer = $this->getViewer(); $package = id(new PhabricatorOwnersPackageQuery())->setViewer($viewer)->withIDs(array($request->getURIData('id')))->needPaths(true)->executeOne(); if (!$package) { return new Aphront404Response(); } $paths = $package->getPaths(); $repository_phids = array(); foreach ($paths as $path) { $repository_phids[$path->getRepositoryPHID()] = true; } if ($repository_phids) { $repositories = id(new PhabricatorRepositoryQuery())->setViewer($viewer)->withPHIDs(array_keys($repository_phids))->execute(); $repositories = mpull($repositories, null, 'getPHID'); } else { $repositories = array(); } $actions = $this->buildPackageActionView($package); $properties = $this->buildPackagePropertyView($package); $properties->setActionList($actions); $header = id(new PHUIHeaderView())->setUser($viewer)->setHeader($package->getName())->setPolicyObject($package); $panel = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties); $commit_views = array(); $commit_uri = id(new PhutilURI('/audit/'))->setQueryParams(array('auditorPHIDs' => $package->getPHID())); $attention_commits = id(new DiffusionCommitQuery())->setViewer($request->getUser())->withAuditorPHIDs(array($package->getPHID()))->withAuditStatus(DiffusionCommitQuery::AUDIT_STATUS_CONCERN)->needCommitData(true)->setLimit(10)->execute(); if ($attention_commits) { $view = id(new PhabricatorAuditListView())->setUser($viewer)->setCommits($attention_commits); $commit_views[] = array('view' => $view, 'header' => pht('Commits in this Package that Need Attention'), 'button' => id(new PHUIButtonView())->setTag('a')->setHref($commit_uri->alter('status', 'open'))->setText(pht('View All Problem Commits'))); } $all_commits = id(new DiffusionCommitQuery())->setViewer($request->getUser())->withAuditorPHIDs(array($package->getPHID()))->needCommitData(true)->setLimit(100)->execute(); $view = id(new PhabricatorAuditListView())->setUser($viewer)->setCommits($all_commits)->setNoDataString(pht('No commits in this package.')); $commit_views[] = array('view' => $view, 'header' => pht('Recent Commits in Package'), 'button' => id(new PHUIButtonView())->setTag('a')->setHref($commit_uri)->setText(pht('View All Package Commits'))); $phids = array(); foreach ($commit_views as $commit_view) { $phids[] = $commit_view['view']->getRequiredHandlePHIDs(); } $phids = array_mergev($phids); $handles = $this->loadViewerHandles($phids); $commit_panels = array(); foreach ($commit_views as $commit_view) { $commit_panel = new PHUIObjectBoxView(); $header = new PHUIHeaderView(); $header->setHeader($commit_view['header']); if (isset($commit_view['button'])) { $header->addActionLink($commit_view['button']); } $commit_view['view']->setHandles($handles); $commit_panel->setHeader($header); $commit_panel->appendChild($commit_view['view']); $commit_panels[] = $commit_panel; } $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($package->getName()); $timeline = $this->buildTransactionTimeline($package, new PhabricatorOwnersPackageTransactionQuery()); $timeline->setShouldTerminate(true); return $this->buildApplicationPage(array($crumbs, $panel, $this->renderPathsTable($paths, $repositories), $commit_panels, $timeline), array('title' => $package->getName())); }
public function processRequest(AphrontRequest $request) { $user = $this->getUser(); $viewer = $request->getUser(); $keys = id(new PhabricatorAuthSSHKeyQuery())->setViewer($viewer)->withObjectPHIDs(array($user->getPHID()))->withIsActive(true)->execute(); $table = id(new PhabricatorAuthSSHKeyTableView())->setUser($viewer)->setKeys($keys)->setCanEdit(true)->setNoDataString(pht("You haven't added any SSH Public Keys.")); $panel = new PHUIObjectBoxView(); $header = new PHUIHeaderView(); $ssh_actions = PhabricatorAuthSSHKeyTableView::newKeyActionsMenu($viewer, $user); $header->setHeader(pht('SSH Public Keys')); $header->addActionLink($ssh_actions); $panel->setHeader($header); $panel->setTable($table); return $panel; }
protected function processDiffusionRequest(AphrontRequest $request) { $user = $request->getUser(); // This controller doesn't use blob/path stuff, just pass the dictionary // in directly instead of using the AphrontRequest parsing mechanism. $data = $request->getURIMap(); $data['user'] = $user; $drequest = DiffusionRequest::newFromDictionary($data); $this->diffusionRequest = $drequest; if ($request->getStr('diff')) { return $this->buildRawDiffResponse($drequest); } $repository = $drequest->getRepository(); $callsign = $repository->getCallsign(); $content = array(); $commit = id(new DiffusionCommitQuery())->setViewer($request->getUser())->withRepository($repository)->withIdentifiers(array($drequest->getCommit()))->needCommitData(true)->needAuditRequests(true)->executeOne(); $crumbs = $this->buildCrumbs(array('commit' => true)); if (!$commit) { $exists = $this->callConduitWithDiffusionRequest('diffusion.existsquery', array('commit' => $drequest->getCommit())); if (!$exists) { return new Aphront404Response(); } $error = id(new PHUIInfoView())->setTitle(pht('Commit Still Parsing'))->appendChild(pht('Failed to load the commit because the commit has not been ' . 'parsed yet.')); return $this->buildApplicationPage(array($crumbs, $error), array('title' => pht('Commit Still Parsing'))); } $audit_requests = $commit->getAudits(); $this->auditAuthorityPHIDs = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user); $commit_data = $commit->getCommitData(); $is_foreign = $commit_data->getCommitDetail('foreign-svn-stub'); if ($is_foreign) { $subpath = $commit_data->getCommitDetail('svn-subpath'); $error_panel = new PHUIInfoView(); $error_panel->setTitle(pht('Commit Not Tracked')); $error_panel->setSeverity(PHUIInfoView::SEVERITY_WARNING); $error_panel->appendChild(pht("This Diffusion repository is configured to track only one " . "subdirectory of the entire Subversion repository, and this commit " . "didn't affect the tracked subdirectory ('%s'), so no " . "information is available.", $subpath)); $content[] = $error_panel; } else { $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine(); $engine->setConfig('viewer', $user); require_celerity_resource('phabricator-remarkup-css'); $parents = $this->callConduitWithDiffusionRequest('diffusion.commitparentsquery', array('commit' => $drequest->getCommit())); if ($parents) { $parents = id(new DiffusionCommitQuery())->setViewer($user)->withRepository($repository)->withIdentifiers($parents)->execute(); } $headsup_view = id(new PHUIHeaderView())->setHeader(nonempty($commit->getSummary(), pht('Commit Detail'))); $headsup_actions = $this->renderHeadsupActionList($commit, $repository); $commit_properties = $this->loadCommitProperties($commit, $commit_data, $parents, $audit_requests); $property_list = id(new PHUIPropertyListView())->setHasKeyboardShortcuts(true)->setUser($user)->setObject($commit); foreach ($commit_properties as $key => $value) { $property_list->addProperty($key, $value); } $message = $commit_data->getCommitMessage(); $revision = $commit->getCommitIdentifier(); $message = $this->linkBugtraq($message); $message = $engine->markupText($message); $property_list->invokeWillRenderEvent(); $property_list->setActionList($headsup_actions); $detail_list = new PHUIPropertyListView(); $detail_list->addSectionHeader(pht('Description'), PHUIPropertyListView::ICON_SUMMARY); $detail_list->addTextContent(phutil_tag('div', array('class' => 'diffusion-commit-message phabricator-remarkup'), $message)); $headsup_view->setTall(true); $object_box = id(new PHUIObjectBoxView())->setHeader($headsup_view)->addPropertyList($property_list)->addPropertyList($detail_list); $content[] = $object_box; } $content[] = $this->buildComments($commit); $hard_limit = 1000; if ($commit->isImported()) { $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest($drequest); $change_query->setLimit($hard_limit + 1); $changes = $change_query->loadChanges(); } else { $changes = array(); } $was_limited = count($changes) > $hard_limit; if ($was_limited) { $changes = array_slice($changes, 0, $hard_limit); } $content[] = $this->buildMergesTable($commit); $highlighted_audits = $commit->getAuthorityAudits($user, $this->auditAuthorityPHIDs); $count = count($changes); $bad_commit = null; if ($count == 0) { $bad_commit = queryfx_one(id(new PhabricatorRepository())->establishConnection('r'), 'SELECT * FROM %T WHERE fullCommitName = %s', PhabricatorRepository::TABLE_BADCOMMIT, 'r' . $callsign . $commit->getCommitIdentifier()); } $show_changesets = false; if ($bad_commit) { $content[] = $this->renderStatusMessage(pht('Bad Commit'), $bad_commit['description']); } else { if ($is_foreign) { // Don't render anything else. } else { if (!$commit->isImported()) { $content[] = $this->renderStatusMessage(pht('Still Importing...'), pht('This commit is still importing. Changes will be visible once ' . 'the import finishes.')); } else { if (!count($changes)) { $content[] = $this->renderStatusMessage(pht('Empty Commit'), pht('This commit is empty and does not affect any paths.')); } else { if ($was_limited) { $content[] = $this->renderStatusMessage(pht('Enormous Commit'), pht('This commit is enormous, and affects more than %d files. ' . 'Changes are not shown.', $hard_limit)); } else { $show_changesets = true; // The user has clicked "Show All Changes", and we should show all the // changes inline even if there are more than the soft limit. $show_all_details = $request->getBool('show_all'); $change_panel = new PHUIObjectBoxView(); $header = new PHUIHeaderView(); $header->setHeader(pht('Changes (%s)', new PhutilNumber($count))); $change_panel->setID('toc'); if ($count > self::CHANGES_LIMIT && !$show_all_details) { $icon = id(new PHUIIconView())->setIconFont('fa-files-o'); $button = id(new PHUIButtonView())->setText(pht('Show All Changes'))->setHref('?show_all=true')->setTag('a')->setIcon($icon); $warning_view = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_WARNING)->setTitle(pht('Very Large Commit'))->appendChild(pht('This commit is very large. Load each file individually.')); $change_panel->setInfoView($warning_view); $header->addActionLink($button); } $changesets = DiffusionPathChange::convertToDifferentialChangesets($user, $changes); // TODO: This table and panel shouldn't really be separate, but we need // to clean up the "Load All Files" interaction first. $change_table = $this->buildTableOfContents($changesets); $change_panel->setTable($change_table); $change_panel->setHeader($header); $content[] = $change_panel; $vcs = $repository->getVersionControlSystem(); switch ($vcs) { case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $vcs_supports_directory_changes = true; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $vcs_supports_directory_changes = false; break; default: throw new Exception(pht('Unknown VCS.')); } $references = array(); foreach ($changesets as $key => $changeset) { $file_type = $changeset->getFileType(); if ($file_type == DifferentialChangeType::FILE_DIRECTORY) { if (!$vcs_supports_directory_changes) { unset($changesets[$key]); continue; } } $references[$key] = $drequest->generateURI(array('action' => 'rendering-ref', 'path' => $changeset->getFilename())); } // TODO: Some parts of the views still rely on properties of the // DifferentialChangeset. Make the objects ephemeral to make sure we don't // accidentally save them, and then set their ID to the appropriate ID for // this application (the path IDs). $path_ids = array_flip(mpull($changes, 'getPath')); foreach ($changesets as $changeset) { $changeset->makeEphemeral(); $changeset->setID($path_ids[$changeset->getFilename()]); } if ($count <= self::CHANGES_LIMIT || $show_all_details) { $visible_changesets = $changesets; } else { $visible_changesets = array(); $inlines = PhabricatorAuditInlineComment::loadDraftAndPublishedComments($user, $commit->getPHID()); $path_ids = mpull($inlines, null, 'getPathID'); foreach ($changesets as $key => $changeset) { if (array_key_exists($changeset->getID(), $path_ids)) { $visible_changesets[$key] = $changeset; } } } $change_list_title = DiffusionView::nameCommit($repository, $commit->getCommitIdentifier()); $change_list = new DifferentialChangesetListView(); $change_list->setTitle($change_list_title); $change_list->setChangesets($changesets); $change_list->setVisibleChangesets($visible_changesets); $change_list->setRenderingReferences($references); $change_list->setRenderURI('/diffusion/' . $callsign . '/diff/'); $change_list->setRepository($repository); $change_list->setUser($user); // TODO: Try to setBranch() to something reasonable here? $change_list->setStandaloneURI('/diffusion/' . $callsign . '/diff/'); $change_list->setRawFileURIs(null, '/diffusion/' . $callsign . '/diff/?view=r'); $change_list->setInlineCommentControllerURI('/diffusion/inline/edit/' . phutil_escape_uri($commit->getPHID()) . '/'); $content[] = $change_list->render(); } } } } } $content[] = $this->renderAddCommentPanel($commit, $audit_requests); $commit_id = 'r' . $callsign . $commit->getCommitIdentifier(); $short_name = DiffusionView::nameCommit($repository, $commit->getCommitIdentifier()); $prefs = $user->loadPreferences(); $pref_filetree = PhabricatorUserPreferences::PREFERENCE_DIFF_FILETREE; $pref_collapse = PhabricatorUserPreferences::PREFERENCE_NAV_COLLAPSED; $show_filetree = $prefs->getPreference($pref_filetree); $collapsed = $prefs->getPreference($pref_collapse); if ($show_changesets && $show_filetree) { $nav = id(new DifferentialChangesetFileTreeSideNavBuilder())->setTitle($short_name)->setBaseURI(new PhutilURI('/' . $commit_id))->build($changesets)->setCrumbs($crumbs)->setCollapsed((bool) $collapsed)->appendChild($content); $content = $nav; } else { $content = array($crumbs, $content); } return $this->buildApplicationPage($content, array('title' => $commit_id, 'pageObjects' => array($commit->getPHID()))); }
private function buildTagListTable(DiffusionRequest $drequest) { $viewer = $this->getRequest()->getUser(); $repository = $drequest->getRepository(); switch ($repository->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: // no tags in SVN return null; } $tag_limit = 15; $tags = array(); $tags = DiffusionRepositoryTag::newFromConduit($this->callConduitWithDiffusionRequest('diffusion.tagsquery', array('commit' => null, 'limit' => $tag_limit + 1))); if (!$tags) { return null; } $more_tags = count($tags) > $tag_limit; $tags = array_slice($tags, 0, $tag_limit); $commits = id(new DiffusionCommitQuery())->setViewer($viewer)->withIdentifiers(mpull($tags, 'getCommitIdentifier'))->withRepository($repository)->needCommitData(true)->execute(); $view = id(new DiffusionTagListView())->setUser($viewer)->setDiffusionRequest($drequest)->setTags($tags)->setCommits($commits); $phids = $view->getRequiredHandlePHIDs(); $handles = $this->loadViewerHandles($phids); $view->setHandles($handles); $panel = new PHUIObjectBoxView(); $header = new PHUIHeaderView(); $header->setHeader(pht('Tags')); if ($more_tags) { $header->setSubHeader(pht('Showing the %d most recent tags.', $tag_limit)); } $icon = id(new PHUIIconView())->setIconFont('fa-tag'); $button = new PHUIButtonView(); $button->setText(pht('Show All Tags')); $button->setTag('a'); $button->setIcon($icon); $button->setHref($drequest->generateURI(array('action' => 'tags'))); $header->addActionLink($button); $panel->setHeader($header); $panel->setTable($view); return $panel; }
public function processRequest(AphrontRequest $request) { $user = $this->getUser(); $editable = PhabricatorEnv::getEnvConfig('account.editable'); $uri = $request->getRequestURI(); $uri->setQueryParams(array()); if ($editable) { $new = $request->getStr('new'); if ($new) { return $this->returnNewAddressResponse($request, $uri, $new); } $delete = $request->getInt('delete'); if ($delete) { return $this->returnDeleteAddressResponse($request, $uri, $delete); } } $verify = $request->getInt('verify'); if ($verify) { return $this->returnVerifyAddressResponse($request, $uri, $verify); } $primary = $request->getInt('primary'); if ($primary) { return $this->returnPrimaryAddressResponse($request, $uri, $primary); } $emails = id(new PhabricatorUserEmail())->loadAllWhere('userPHID = %s ORDER BY address', $user->getPHID()); $rowc = array(); $rows = array(); foreach ($emails as $email) { $button_verify = javelin_tag('a', array('class' => 'button small grey', 'href' => $uri->alter('verify', $email->getID()), 'sigil' => 'workflow'), pht('Verify')); $button_make_primary = javelin_tag('a', array('class' => 'button small grey', 'href' => $uri->alter('primary', $email->getID()), 'sigil' => 'workflow'), pht('Make Primary')); $button_remove = javelin_tag('a', array('class' => 'button small grey', 'href' => $uri->alter('delete', $email->getID()), 'sigil' => 'workflow'), pht('Remove')); $button_primary = phutil_tag('a', array('class' => 'button small disabled'), pht('Primary')); if (!$email->getIsVerified()) { $action = $button_verify; } else { if ($email->getIsPrimary()) { $action = $button_primary; } else { $action = $button_make_primary; } } if ($email->getIsPrimary()) { $remove = $button_primary; $rowc[] = 'highlighted'; } else { $remove = $button_remove; $rowc[] = null; } $rows[] = array($email->getAddress(), $action, $remove); } $table = new AphrontTableView($rows); $table->setHeaders(array(pht('Email'), pht('Status'), pht('Remove'))); $table->setColumnClasses(array('wide', 'action', 'action')); $table->setRowClasses($rowc); $table->setColumnVisibility(array(true, true, $editable)); $view = new PHUIObjectBoxView(); $header = new PHUIHeaderView(); $header->setHeader(pht('Email Addresses')); if ($editable) { $button = new PHUIButtonView(); $button->setText(pht('Add New Address')); $button->setTag('a'); $button->setHref($uri->alter('new', 'true')); $button->setIcon('fa-plus'); $button->addSigil('workflow'); $header->addActionLink($button); } $view->setHeader($header); $view->setTable($table); return $view; }
private function buildTagListTable(DiffusionRequest $drequest) { $viewer = $this->getRequest()->getUser(); $tag_limit = 15; $tags = array(); try { $tags = DiffusionRepositoryTag::newFromConduit($this->callConduitWithDiffusionRequest('diffusion.tagsquery', array('commit' => null, 'limit' => $tag_limit + 1))); } catch (ConduitException $e) { if ($e->getMessage() != 'ERR-UNSUPPORTED-VCS') { throw $e; } } if (!$tags) { return null; } $more_tags = count($tags) > $tag_limit; $tags = array_slice($tags, 0, $tag_limit); $commits = id(new DiffusionCommitQuery())->setViewer($viewer)->withIdentifiers(mpull($tags, 'getCommitIdentifier'))->withRepository($drequest->getRepository())->needCommitData(true)->execute(); $view = id(new DiffusionTagListView())->setUser($viewer)->setDiffusionRequest($drequest)->setTags($tags)->setCommits($commits); $phids = $view->getRequiredHandlePHIDs(); $handles = $this->loadViewerHandles($phids); $view->setHandles($handles); $panel = new PHUIObjectBoxView(); $header = new PHUIHeaderView(); $header->setHeader(pht('Tags')); if ($more_tags) { $header->setSubHeader(pht('Showing the %d most recent tags.', $tag_limit)); } $icon = id(new PHUIIconView())->setIconFont('fa-tag'); $button = new PHUIButtonView(); $button->setText(pht('Show All Tags')); $button->setTag('a'); $button->setIcon($icon); $button->setHref($drequest->generateURI(array('action' => 'tags'))); $header->addActionLink($button); $panel->setHeader($header); $panel->appendChild($view); return $panel; }
private function renderKeyListView(AphrontRequest $request) { $user = $this->getUser(); $viewer = $request->getUser(); $keys = id(new PhabricatorUserSSHKey())->loadAllWhere('userPHID = %s', $user->getPHID()); $rows = array(); foreach ($keys as $key) { $rows[] = array(phutil_tag('a', array('href' => $this->getPanelURI('?edit=' . $key->getID())), $key->getName()), $key->getKeyComment(), $key->getKeyType(), phabricator_date($key->getDateCreated(), $viewer), phabricator_time($key->getDateCreated(), $viewer), javelin_tag('a', array('href' => $this->getPanelURI('?delete=' . $key->getID()), 'class' => 'small grey button', 'sigil' => 'workflow'), pht('Delete'))); } $table = new AphrontTableView($rows); $table->setNoDataString(pht("You haven't added any SSH Public Keys.")); $table->setHeaders(array(pht('Name'), pht('Comment'), pht('Type'), pht('Created'), pht('Time'), '')); $table->setColumnClasses(array('wide pri', '', '', '', 'right', 'action')); $panel = new PHUIObjectBoxView(); $header = new PHUIHeaderView(); $upload_icon = id(new PHUIIconView())->setIconFont('fa-upload'); $upload_button = id(new PHUIButtonView())->setText(pht('Upload Public Key'))->setHref($this->getPanelURI('?edit=true'))->setTag('a')->setIcon($upload_icon); try { PhabricatorSSHKeyGenerator::assertCanGenerateKeypair(); $can_generate = true; } catch (Exception $ex) { $can_generate = false; } $generate_icon = id(new PHUIIconView())->setIconFont('fa-lock'); $generate_button = id(new PHUIButtonView())->setText(pht('Generate Keypair'))->setHref($this->getPanelURI('?generate=true'))->setTag('a')->setWorkflow(true)->setDisabled(!$can_generate)->setIcon($generate_icon); $header->setHeader(pht('SSH Public Keys')); $header->addActionLink($generate_button); $header->addActionLink($upload_button); $panel->setHeader($header); $panel->appendChild($table); return $panel; }