diff --git a/src/applications/auth/controller/config/PhabricatorAuthListController.php b/src/applications/auth/controller/config/PhabricatorAuthListController.php index 421e3197a2..3c774f718a 100644 --- a/src/applications/auth/controller/config/PhabricatorAuthListController.php +++ b/src/applications/auth/controller/config/PhabricatorAuthListController.php @@ -1,136 +1,136 @@ getRequest(); $viewer = $request->getUser(); $configs = id(new PhabricatorAuthProviderConfigQuery()) ->setViewer($viewer) ->execute(); $list = new PHUIObjectItemListView(); foreach ($configs as $config) { $item = new PHUIObjectItemView(); $id = $config->getID(); $edit_uri = $this->getApplicationURI('config/edit/'.$id.'/'); $enable_uri = $this->getApplicationURI('config/enable/'.$id.'/'); $disable_uri = $this->getApplicationURI('config/disable/'.$id.'/'); $provider = $config->getProvider(); if ($provider) { $name = $provider->getProviderName(); } else { $name = $config->getProviderType().' ('.$config->getProviderClass().')'; } $item ->setHeader($name); if ($provider) { $item->setHref($edit_uri); } else { $item->addAttribute(pht('Provider Implementation Missing!')); } $domain = null; if ($provider) { $domain = $provider->getProviderDomain(); if ($domain !== 'self') { $item->addAttribute($domain); } } if ($config->getShouldAllowRegistration()) { $item->addAttribute(pht('Allows Registration')); } if ($config->getIsEnabled()) { $item->setBarColor('green'); $item->addAction( id(new PHUIListItemView()) - ->setIcon('delete') + ->setIcon('fa-times') ->setHref($disable_uri) ->addSigil('workflow')); } else { $item->setBarColor('grey'); - $item->addIcon('delete-grey', pht('Disabled')); + $item->addIcon('fa-times grey', pht('Disabled')); $item->addAction( id(new PHUIListItemView()) - ->setIcon('new') + ->setIcon('fa-plus') ->setHref($enable_uri) ->addSigil('workflow')); } $list->addItem($item); } $list->setNoDataString( pht( '%s You have not added authentication providers yet. Use "%s" to add '. 'a provider, which will let users register new Phabricator accounts '. 'and log in.', phutil_tag( 'strong', array(), pht('No Providers Configured:')), phutil_tag( 'a', array( 'href' => $this->getApplicationURI('config/new/'), ), pht('Add Authentication Provider')))); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Auth Providers')); $config_name = 'auth.email-domains'; $config_href = '/config/edit/'.$config_name.'/'; $config_link = phutil_tag( 'a', array( 'href' => $config_href, 'target' => '_blank', ), $config_name); $warning = new AphrontErrorView(); $email_domains = PhabricatorEnv::getEnvConfig($config_name); if ($email_domains) { $warning->setSeverity(AphrontErrorView::SEVERITY_NOTICE); $warning->setTitle(pht('Registration is Restricted')); $warning->appendChild( pht( 'Only users with a verified email address at one of the %s domains '. 'will be able to register a Phabricator account: %s', $config_link, phutil_tag('strong', array(), implode(', ', $email_domains)))); } else { $warning->setSeverity(AphrontErrorView::SEVERITY_WARNING); $warning->setTitle(pht('Anyone Can Register an Account')); $warning->appendChild( pht( 'Anyone who can browse to this Phabricator install will be able to '. 'register an account. To restrict who can register an account, '. 'configure %s.', $config_link)); } return $this->buildApplicationPage( array( $crumbs, $warning, $list, ), array( 'title' => pht('Authentication Providers'), 'device' => true, )); } } diff --git a/src/applications/config/controller/PhabricatorConfigIssueListController.php b/src/applications/config/controller/PhabricatorConfigIssueListController.php index 7e002c92ea..6204836958 100644 --- a/src/applications/config/controller/PhabricatorConfigIssueListController.php +++ b/src/applications/config/controller/PhabricatorConfigIssueListController.php @@ -1,87 +1,87 @@ getRequest(); $user = $request->getUser(); $nav = $this->buildSideNavView(); $nav->selectFilter('issue/'); $issues = PhabricatorSetupCheck::runAllChecks(); PhabricatorSetupCheck::setOpenSetupIssueCount( PhabricatorSetupCheck::countUnignoredIssues($issues)); $list = $this->buildIssueList($issues); $list->setNoDataString(pht("There are no open setup issues.")); $header = id(new PHUIHeaderView()) ->setHeader(pht('Open Phabricator Setup Issues')); $nav->appendChild( array( $header, $list, )); $title = pht('Setup Issues'); $crumbs = $this ->buildApplicationCrumbs($nav) ->addTextCrumb(pht('Setup'), $this->getApplicationURI('issue/')); $nav->setCrumbs($crumbs); return $this->buildApplicationPage( $nav, array( 'title' => $title, 'device' => true, )); } private function buildIssueList(array $issues) { assert_instances_of($issues, 'PhabricatorSetupIssue'); $list = new PHUIObjectItemListView(); $list->setCards(true); $ignored_items = array(); foreach ($issues as $issue) { $href = $this->getApplicationURI('/issue/'.$issue->getIssueKey().'/'); $item = id(new PHUIObjectItemView()) ->setHeader($issue->getName()) ->setHref($href) ->addAttribute($issue->getSummary()); if (!$issue->getIsIgnored()) { $item->setBarColor('yellow'); $item->addAction( id(new PHUIListItemView()) - ->setIcon('unpublish') + ->setIcon('fa-eye-slash') ->setWorkflow(true) ->setName(pht('Ignore')) ->setHref('/config/ignore/'.$issue->getIssueKey().'/')); $list->addItem($item); } else { $item->addIcon('none', pht('Ignored')); $item->setDisabled(true); $item->addAction( id(new PHUIListItemView()) - ->setIcon('preview') + ->setIcon('fa-eye') ->setWorkflow(true) ->setName(pht('Unignore')) ->setHref('/config/unignore/'.$issue->getIssueKey().'/')); $item->setBarColor('none'); $ignored_items[] = $item; } } foreach ($ignored_items as $item) { $list->addItem($item); } return $list; } } diff --git a/src/applications/daemon/controller/PhabricatorWorkerTaskDetailController.php b/src/applications/daemon/controller/PhabricatorWorkerTaskDetailController.php index 04ec5a4490..169df03d84 100644 --- a/src/applications/daemon/controller/PhabricatorWorkerTaskDetailController.php +++ b/src/applications/daemon/controller/PhabricatorWorkerTaskDetailController.php @@ -1,268 +1,268 @@ id = $data['id']; } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $task = id(new PhabricatorWorkerActiveTask())->load($this->id); if (!$task) { $task = id(new PhabricatorWorkerArchiveTask())->load($this->id); } if (!$task) { $title = pht('Task Does Not Exist'); $error_view = new AphrontErrorView(); $error_view->setTitle(pht('No Such Task')); $error_view->appendChild(phutil_tag( 'p', array(), pht('This task may have recently been garbage collected.'))); $error_view->setSeverity(AphrontErrorView::SEVERITY_NODATA); $content = $error_view; } else { $title = pht('Task %d', $task->getID()); $header = id(new PHUIHeaderView()) ->setHeader(pht('Task %d (%s)', $task->getID(), $task->getTaskClass())); $actions = $this->buildActionListView($task); $properties = $this->buildPropertyListView($task, $actions); $object_box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); $retry_head = id(new PHUIHeaderView()) ->setHeader(pht('Retries')); $retry_info = $this->buildRetryListView($task); $retry_box = id(new PHUIObjectBoxView()) ->setHeader($retry_head) ->addPropertyList($retry_info); $content = array( $object_box, $retry_box, ); } $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($title); return $this->buildApplicationPage( array( $crumbs, $content, ), array( 'title' => $title, 'device' => true, )); } private function buildActionListView(PhabricatorWorkerTask $task) { $request = $this->getRequest(); $user = $request->getUser(); $id = $task->getID(); $view = id(new PhabricatorActionListView()) ->setUser($user) ->setObjectURI($request->getRequestURI()); if ($task->isArchived()) { $result_success = PhabricatorWorkerArchiveTask::RESULT_SUCCESS; $can_retry = ($task->getResult() != $result_success); $view->addAction( id(new PhabricatorActionView()) ->setName(pht('Retry Task')) ->setHref($this->getApplicationURI('/task/'.$id.'/retry/')) - ->setIcon('undo') + ->setIcon('fa-refresh') ->setWorkflow(true) ->setDisabled(!$can_retry)); } else { $view->addAction( id(new PhabricatorActionView()) ->setName(pht('Cancel Task')) ->setHref($this->getApplicationURI('/task/'.$id.'/cancel/')) - ->setIcon('delete') + ->setIcon('fa-times') ->setWorkflow(true)); } $can_release = (!$task->isArchived()) && ($task->getLeaseOwner()); $view->addAction( id(new PhabricatorActionView()) ->setName(pht('Free Lease')) ->setHref($this->getApplicationURI('/task/'.$id.'/release/')) - ->setIcon('unlock') + ->setIcon('fa-unlock') ->setWorkflow(true) ->setDisabled(!$can_release)); return $view; } private function buildPropertyListView( PhabricatorWorkerTask $task, PhabricatorActionListView $actions) { $viewer = $this->getRequest()->getUser(); $view = new PHUIPropertyListView(); $view->setActionList($actions); if ($task->isArchived()) { switch ($task->getResult()) { case PhabricatorWorkerArchiveTask::RESULT_SUCCESS: $status = pht('Complete'); break; case PhabricatorWorkerArchiveTask::RESULT_FAILURE: $status = pht('Failed'); break; case PhabricatorWorkerArchiveTask::RESULT_CANCELLED: $status = pht('Cancelled'); break; default: throw new Exception("Unknown task status!"); } } else { $status = pht('Queued'); } $view->addProperty( pht('Task Status'), $status); $view->addProperty( pht('Task Class'), $task->getTaskClass()); if ($task->getLeaseExpires()) { if ($task->getLeaseExpires() > time()) { $lease_status = pht('Leased'); } else { $lease_status = pht('Lease Expired'); } } else { $lease_status = phutil_tag('em', array(), pht('Not Leased')); } $view->addProperty( pht('Lease Status'), $lease_status); $view->addProperty( pht('Lease Owner'), $task->getLeaseOwner() ? $task->getLeaseOwner() : phutil_tag('em', array(), pht('None'))); if ($task->getLeaseExpires() && $task->getLeaseOwner()) { $expires = ($task->getLeaseExpires() - time()); $expires = phabricator_format_relative_time_detailed($expires); } else { $expires = phutil_tag('em', array(), pht('None')); } $view->addProperty( pht('Lease Expires'), $expires); if ($task->isArchived()) { $duration = number_format($task->getDuration()).' us'; } else { $duration = phutil_tag('em', array(), pht('Not Completed')); } $view->addProperty( pht('Duration'), $duration); $data = id(new PhabricatorWorkerTaskData())->load($task->getDataID()); $task->setData($data->getData()); $worker = $task->getWorkerInstance(); $data = $worker->renderForDisplay($viewer); $view->addProperty( pht('Data'), $data); return $view; } private function buildRetryListView(PhabricatorWorkerTask $task) { $view = new PHUIPropertyListView(); $data = id(new PhabricatorWorkerTaskData())->load($task->getDataID()); $task->setData($data->getData()); $worker = $task->getWorkerInstance(); $view->addProperty( pht('Failure Count'), $task->getFailureCount()); $retry_count = $worker->getMaximumRetryCount(); if ($retry_count === null) { $max_retries = phutil_tag('em', array(), pht('Retries Forever')); $retry_count = INF; } else { $max_retries = $retry_count; } $view->addProperty( pht('Maximum Retries'), $max_retries); $projection = clone $task; $projection->makeEphemeral(); $next = array(); for ($ii = $task->getFailureCount(); $ii < $retry_count; $ii++) { $projection->setFailureCount($ii); $next[] = $worker->getWaitBeforeRetry($projection); if (count($next) > 10) { break; } } if ($next) { $cumulative = 0; foreach ($next as $key => $duration) { if ($duration === null) { $duration = 60; } $cumulative += $duration; $next[$key] = phabricator_format_relative_time($cumulative); } if ($ii != $retry_count) { $next[] = '...'; } $retries_in = implode(', ', $next); } else { $retries_in = pht('No More Retries'); } $view->addProperty( pht('Retries After'), $retries_in); return $view; } } diff --git a/src/applications/differential/landing/DifferentialLandingToGitHub.php b/src/applications/differential/landing/DifferentialLandingToGitHub.php index 00c5362b22..24a1abe5b0 100644 --- a/src/applications/differential/landing/DifferentialLandingToGitHub.php +++ b/src/applications/differential/landing/DifferentialLandingToGitHub.php @@ -1,178 +1,178 @@ getUser(); $this->init($viewer, $repository); $workspace = $this->getGitWorkspace($repository); try { id(new DifferentialLandingToHostedGit()) ->commitRevisionToWorkspace( $revision, $workspace, $viewer); } catch (Exception $e) { throw new PhutilProxyException( 'Failed to commit patch', $e); } try { $this->pushWorkspaceRepository($repository, $workspace); } catch (Exception $e) { // If it's a permission problem, we know more than git. $dialog = $this->verifyRemotePermissions($viewer, $revision, $repository); if ($dialog) { return $dialog; } // Else, throw what git said. throw new PhutilProxyException( 'Failed to push changes upstream', $e); } } /** * returns PhabricatorActionView or an array of PhabricatorActionView or null. */ public function createMenuItem( PhabricatorUser $viewer, DifferentialRevision $revision, PhabricatorRepository $repository) { $vcs = $repository->getVersionControlSystem(); if ($vcs !== PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) { return; } if ($repository->isHosted()) { return; } try { // These throw when failing. $this->init($viewer, $repository); $this->findGitHubRepo($repository); } catch (Exception $e) { return; } return $this->createActionView($revision, pht('Land to GitHub')) - ->setIcon('octocat'); + ->setIcon('fa-cloud-upload'); } public function pushWorkspaceRepository( PhabricatorRepository $repository, ArcanistRepositoryAPI $workspace) { $token = $this->getAccessToken(); $github_repo = $this->findGitHubRepo($repository); $remote = urisprintf( 'https://%s:x-oauth-basic@%s/%s.git', $token, $this->provider->getProviderDomain(), $github_repo); $workspace->execxLocal( "push %P HEAD:master", new PhutilOpaqueEnvelope($remote)); } private function init($viewer, $repository) { $repo_uri = $repository->getRemoteURIObject(); $repo_domain = $repo_uri->getDomain(); $this->account = id(new PhabricatorExternalAccountQuery()) ->setViewer($viewer) ->withUserPHIDs(array($viewer->getPHID())) ->withAccountTypes(array("github")) ->withAccountDomains(array($repo_domain)) ->executeOne(); if (!$this->account) { throw new Exception( "No matching GitHub account found for {$repo_domain}."); } $this->provider = PhabricatorAuthProvider::getEnabledProviderByKey( $this->account->getProviderKey()); if (!$this->provider) { throw new Exception("GitHub provider for {$repo_domain} is not enabled."); } } private function findGitHubRepo(PhabricatorRepository $repository) { $repo_uri = $repository->getRemoteURIObject(); $repo_path = $repo_uri->getPath(); if (substr($repo_path, -4) == '.git') { $repo_path = substr($repo_path, 0, -4); } $repo_path = ltrim($repo_path, '/'); return $repo_path; } private function getAccessToken() { return $this->provider->getOAuthAccessToken($this->account); } private function verifyRemotePermissions($viewer, $revision, $repository) { $github_user = $this->account->getUsername(); $github_repo = $this->findGitHubRepo($repository); $uri = urisprintf( 'https://api.github.com/repos/%s/collaborators/%s', $github_repo, $github_user); $uri = new PhutilURI($uri); $uri->setQueryParam('access_token', $this->getAccessToken()); list($status, $body, $headers) = id(new HTTPSFuture($uri))->resolve(); // Likely status codes: // 204 No Content: Has permissions. Token might be too weak. // 404 Not Found: Not a collaborator. // 401 Unauthorized: Token is bad/revoked. $no_permission = ($status->getStatusCode() == 404); if ($no_permission) { throw new Exception( "You don't have permission to push to this repository. \n". "Push permissions for this repository are managed on GitHub."); } $scopes = BaseHTTPFuture::getHeader($headers, 'X-OAuth-Scopes'); if (strpos($scopes, 'public_repo') === false) { $provider_key = $this->provider->getProviderKey(); $refresh_token_uri = new PhutilURI("/auth/refresh/{$provider_key}/"); $refresh_token_uri->setQueryParam('scope', 'public_repo'); return id(new AphrontDialogView()) ->setUser($viewer) ->setTitle(pht('Stronger token needed')) ->appendChild(pht( 'In order to complete this action, you need a '. 'stronger GitHub token.')) ->setSubmitURI($refresh_token_uri) ->addCancelButton('/D'.$revision->getId()) ->addSubmitButton(pht('Refresh Account Link')); } } } diff --git a/src/applications/diffusion/controller/DiffusionChangeController.php b/src/applications/diffusion/controller/DiffusionChangeController.php index 74c349c6c3..1c0c81c52b 100644 --- a/src/applications/diffusion/controller/DiffusionChangeController.php +++ b/src/applications/diffusion/controller/DiffusionChangeController.php @@ -1,161 +1,161 @@ diffusionRequest; $viewer = $this->getRequest()->getUser(); $content = array(); $data = $this->callConduitWithDiffusionRequest( 'diffusion.diffquery', array( 'commit' => $drequest->getCommit(), 'path' => $drequest->getPath(), )); $drequest->setCommit($data['effectiveCommit']); $raw_changes = ArcanistDiffChange::newFromConduit($data['changes']); $diff = DifferentialDiff::newFromRawChanges($raw_changes); $changesets = $diff->getChangesets(); $changeset = reset($changesets); if (!$changeset) { // TODO: Refine this. return new Aphront404Response(); } $repository = $drequest->getRepository(); $callsign = $repository->getCallsign(); $commit = $drequest->getRawCommit(); $changesets = array( 0 => $changeset, ); $changeset_view = new DifferentialChangesetListView(); $changeset_view->setTitle(pht('Change')); $changeset_view->setChangesets($changesets); $changeset_view->setVisibleChangesets($changesets); $changeset_view->setRenderingReferences( array( 0 => $drequest->generateURI(array('action' => 'rendering-ref')) )); $raw_params = array( 'action' => 'browse', 'params' => array( 'view' => 'raw', ), ); $right_uri = $drequest->generateURI($raw_params); $raw_params['params']['before'] = $drequest->getRawCommit(); $left_uri = $drequest->generateURI($raw_params); $changeset_view->setRawFileURIs($left_uri, $right_uri); $changeset_view->setRenderURI('/diffusion/'.$callsign.'/diff/'); $changeset_view->setWhitespace( DifferentialChangesetParser::WHITESPACE_SHOW_ALL); $changeset_view->setUser($this->getRequest()->getUser()); // TODO: This is pretty awkward, unify the CSS between Diffusion and // Differential better. require_celerity_resource('differential-core-view-css'); $content[] = $changeset_view->render(); $crumbs = $this->buildCrumbs( array( 'branch' => true, 'path' => true, 'view' => 'change', )); $links = $this->renderPathLinks($drequest, $mode = 'browse'); $header = id(new PHUIHeaderView()) ->setHeader($links) ->setUser($viewer) ->setPolicyObject($drequest->getRepository()); $actions = $this->buildActionView($drequest); $properties = $this->buildPropertyView($drequest, $actions); $object_box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); return $this->buildApplicationPage( array( $crumbs, $object_box, $content, ), array( 'title' => pht('Change'), )); } private function buildActionView(DiffusionRequest $drequest) { $viewer = $this->getRequest()->getUser(); $view = id(new PhabricatorActionListView()) ->setUser($viewer); $history_uri = $drequest->generateURI( array( 'action' => 'history', )); $view->addAction( id(new PhabricatorActionView()) ->setName(pht('View History')) ->setHref($history_uri) - ->setIcon('history')); + ->setIcon('fa-clock-o')); $browse_uri = $drequest->generateURI( array( 'action' => 'browse', )); $view->addAction( id(new PhabricatorActionView()) ->setName(pht('Browse Content')) ->setHref($browse_uri) - ->setIcon('file')); + ->setIcon('fa-files-o')); return $view; } protected function buildPropertyView( DiffusionRequest $drequest, PhabricatorActionListView $actions) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setActionList($actions); $stable_commit = $drequest->getStableCommitName(); $callsign = $drequest->getRepository()->getCallsign(); $view->addProperty( pht('Commit'), phutil_tag( 'a', array( 'href' => $drequest->generateURI( array( 'action' => 'commit', 'commit' => $stable_commit, )), ), $drequest->getRepository()->formatCommitName($stable_commit))); return $view; } } diff --git a/src/applications/diffusion/controller/DiffusionHistoryController.php b/src/applications/diffusion/controller/DiffusionHistoryController.php index f64687d237..91e4479acf 100644 --- a/src/applications/diffusion/controller/DiffusionHistoryController.php +++ b/src/applications/diffusion/controller/DiffusionHistoryController.php @@ -1,176 +1,176 @@ diffusionRequest; $request = $this->getRequest(); $viewer = $request->getUser(); $repository = $drequest->getRepository(); $page_size = $request->getInt('pagesize', 100); $offset = $request->getInt('offset', 0); $params = array( 'commit' => $drequest->getCommit(), 'path' => $drequest->getPath(), 'offset' => $offset, 'limit' => $page_size + 1); if (!$request->getBool('copies')) { $params['needDirectChanges'] = true; $params['needChildChanges'] = true; } $history_results = $this->callConduitWithDiffusionRequest( 'diffusion.historyquery', $params); $history = DiffusionPathChange::newFromConduit( $history_results['pathChanges']); $pager = new AphrontPagerView(); $pager->setPageSize($page_size); $pager->setOffset($offset); $history = $pager->sliceResults($history); $pager->setURI($request->getRequestURI(), 'offset'); $show_graph = !strlen($drequest->getPath()); $content = array(); $history_table = new DiffusionHistoryTableView(); $history_table->setUser($request->getUser()); $history_table->setDiffusionRequest($drequest); $history_table->setHistory($history); $history_table->loadRevisions(); $phids = $history_table->getRequiredHandlePHIDs(); $handles = $this->loadViewerHandles($phids); $history_table->setHandles($handles); if ($show_graph) { $history_table->setParents($history_results['parents']); $history_table->setIsHead($offset == 0); } $history_panel = new AphrontPanelView(); $history_panel->appendChild($history_table); $history_panel->appendChild($pager); $history_panel->setNoBackground(); $content[] = $history_panel; $header = id(new PHUIHeaderView()) ->setUser($viewer) ->setPolicyObject($repository) ->setHeader($this->renderPathLinks($drequest, $mode = 'history')); $actions = $this->buildActionView($drequest); $properties = $this->buildPropertyView($drequest, $actions); $object_box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); $crumbs = $this->buildCrumbs( array( 'branch' => true, 'path' => true, 'view' => 'history', )); return $this->buildApplicationPage( array( $crumbs, $object_box, $content, ), array( 'device' => true, 'title' => array( pht('History'), pht('%s Repository', $drequest->getRepository()->getCallsign()), ), )); } private function buildActionView(DiffusionRequest $drequest) { $viewer = $this->getRequest()->getUser(); $view = id(new PhabricatorActionListView()) ->setUser($viewer); $browse_uri = $drequest->generateURI( array( 'action' => 'browse', )); $view->addAction( id(new PhabricatorActionView()) ->setName(pht('Browse Content')) ->setHref($browse_uri) - ->setIcon('file')); + ->setIcon('fa-files-o')); // TODO: Sometimes we do have a change view, we need to look at the most // recent history entry to figure it out. $request = $this->getRequest(); if ($request->getBool('copies')) { $branch_name = pht('Hide Copies/Branches'); $branch_icon = 'fork-grey'; $branch_uri = $request->getRequestURI() ->alter('offset', null) ->alter('copies', null); } else { $branch_name = pht('Show Copies/Branches'); $branch_icon = 'fork'; $branch_uri = $request->getRequestURI() ->alter('offset', null) ->alter('copies', true); } $view->addAction( id(new PhabricatorActionView()) ->setName($branch_name) ->setIcon($branch_icon) ->setHref($branch_uri)); return $view; } protected function buildPropertyView( DiffusionRequest $drequest, PhabricatorActionListView $actions) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setActionList($actions); $stable_commit = $drequest->getStableCommitName(); $callsign = $drequest->getRepository()->getCallsign(); $view->addProperty( pht('Commit'), phutil_tag( 'a', array( 'href' => $drequest->generateURI( array( 'action' => 'commit', 'commit' => $stable_commit, )), ), $drequest->getRepository()->formatCommitName($stable_commit))); return $view; } } diff --git a/src/applications/diffusion/controller/DiffusionLintController.php b/src/applications/diffusion/controller/DiffusionLintController.php index f826f33aa8..507581f540 100644 --- a/src/applications/diffusion/controller/DiffusionLintController.php +++ b/src/applications/diffusion/controller/DiffusionLintController.php @@ -1,345 +1,345 @@ getRequest(); $user = $this->getRequest()->getUser(); $drequest = $this->diffusionRequest; if ($request->getStr('lint') !== null) { $controller = new DiffusionLintDetailsController($request); $controller->setDiffusionRequest($drequest); $controller->setCurrentApplication($this->getCurrentApplication()); return $this->delegateToController($controller); } $owners = array(); if (!$drequest) { if (!$request->getArr('owner')) { $owners = array($user->getPHID()); } else { $owners = array(head($request->getArr('owner'))); } $owner_handles = $this->loadViewerHandles($owners); } $codes = $this->loadLintCodes($owners); if ($codes && !$drequest) { // TODO: Build some real Query classes for this stuff. $branches = id(new PhabricatorRepositoryBranch())->loadAllWhere( 'id IN (%Ld)', array_unique(ipull($codes, 'branchID'))); $repositories = id(new PhabricatorRepositoryQuery()) ->setViewer($user) ->withIDs(mpull($branches, 'getRepositoryID')) ->execute(); $drequests = array(); foreach ($branches as $id => $branch) { if (empty($repositories[$branch->getRepositoryID()])) { continue; } $drequests[$id] = DiffusionRequest::newFromDictionary(array( 'user' => $user, 'repository' => $repositories[$branch->getRepositoryID()], 'branch' => $branch->getName(), )); } } $rows = array(); $total = 0; foreach ($codes as $code) { if (!$this->diffusionRequest) { $drequest = idx($drequests, $code['branchID']); } if (!$drequest) { continue; } $total += $code['n']; $href_lint = $drequest->generateURI(array( 'action' => 'lint', 'lint' => $code['code'], )); $href_browse = $drequest->generateURI(array( 'action' => 'browse', 'lint' => $code['code'], )); $href_repo = $drequest->generateURI(array('action' => 'lint')); $rows[] = array( phutil_tag('a', array('href' => $href_lint), $code['n']), phutil_tag('a', array('href' => $href_browse), $code['files']), phutil_tag('a', array('href' => $href_repo), $drequest->getCallsign()), ArcanistLintSeverity::getStringForSeverity($code['maxSeverity']), $code['code'], $code['maxName'], $code['maxDescription'], ); } $table = id(new AphrontTableView($rows)) ->setHeaders(array( pht('Problems'), pht('Files'), pht('Repository'), pht('Severity'), pht('Code'), pht('Name'), pht('Example'), )) ->setColumnVisibility(array(true, true, !$this->diffusionRequest)) ->setColumnClasses(array('n', 'n', '', '', 'pri', '', '')); $content = array(); $link = null; if (!$this->diffusionRequest) { $form = id(new AphrontFormView()) ->setUser($user) ->setMethod('GET') ->appendChild( id(new AphrontFormTokenizerControl()) ->setDatasource('/typeahead/common/users/') ->setLimit(1) ->setName('owner') ->setLabel(pht('Owner')) ->setValue($owner_handles)) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue('Filter')); $content[] = id(new AphrontListFilterView())->appendChild($form); } $content[] = id(new AphrontPanelView()) ->setNoBackground(true) ->setCaption($link) ->appendChild($table); $title = array('Lint'); $crumbs = $this->buildCrumbs( array( 'branch' => true, 'path' => true, 'view' => 'lint', )); if ($this->diffusionRequest) { $title[] = $drequest->getCallsign(); } else { $crumbs->addTextCrumb(pht('All Lint')); } if ($this->diffusionRequest) { $branch = $drequest->loadBranch(); $header = id(new PHUIHeaderView()) ->setHeader($this->renderPathLinks($drequest, 'lint')) ->setUser($user) ->setPolicyObject($drequest->getRepository()); $actions = $this->buildActionView($drequest); $properties = $this->buildPropertyView( $drequest, $branch, $total, $actions); $object_box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); } else { $object_box = null; } return $this->buildApplicationPage( array( $crumbs, $object_box, $content, ), array( 'title' => $title, )); } private function loadLintCodes(array $owner_phids) { $drequest = $this->diffusionRequest; $conn = id(new PhabricatorRepository())->establishConnection('r'); $where = array('1 = 1'); if ($drequest) { $branch = $drequest->loadBranch(); if (!$branch) { return array(); } $where[] = qsprintf($conn, 'branchID = %d', $branch->getID()); if ($drequest->getPath() != '') { $path = '/'.$drequest->getPath(); $is_dir = (substr($path, -1) == '/'); $where[] = ($is_dir ? qsprintf($conn, 'path LIKE %>', $path) : qsprintf($conn, 'path = %s', $path)); } } if ($owner_phids) { $or = array(); $or[] = qsprintf($conn, 'authorPHID IN (%Ls)', $owner_phids); $paths = array(); $packages = id(new PhabricatorOwnersOwner()) ->loadAllWhere('userPHID IN (%Ls)', $owner_phids); if ($packages) { $paths = id(new PhabricatorOwnersPath())->loadAllWhere( 'packageID IN (%Ld)', mpull($packages, 'getPackageID')); } if ($paths) { $repositories = id(new PhabricatorRepositoryQuery()) ->setViewer($this->getRequest()->getUser()) ->withPHIDs(mpull($paths, 'getRepositoryPHID')) ->execute(); $repositories = mpull($repositories, 'getID', 'getPHID'); $branches = id(new PhabricatorRepositoryBranch())->loadAllWhere( 'repositoryID IN (%Ld)', $repositories); $branches = mgroup($branches, 'getRepositoryID'); } foreach ($paths as $path) { $branch = idx( $branches, idx( $repositories, $path->getRepositoryPHID())); if ($branch) { $condition = qsprintf( $conn, '(branchID IN (%Ld) AND path LIKE %>)', array_keys($branch), $path->getPath()); if ($path->getExcluded()) { $where[] = 'NOT '.$condition; } else { $or[] = $condition; } } } $where[] = '('.implode(' OR ', $or).')'; } return queryfx_all( $conn, 'SELECT branchID, code, MAX(severity) AS maxSeverity, MAX(name) AS maxName, MAX(description) AS maxDescription, COUNT(DISTINCT path) AS files, COUNT(*) AS n FROM %T WHERE %Q GROUP BY branchID, code ORDER BY n DESC', PhabricatorRepository::TABLE_LINTMESSAGE, implode(' AND ', $where)); } protected function buildActionView(DiffusionRequest $drequest) { $viewer = $this->getRequest()->getUser(); $view = id(new PhabricatorActionListView()) ->setUser($viewer); $list_uri = $drequest->generateURI( array( 'action' => 'lint', 'lint' => '', )); $view->addAction( id(new PhabricatorActionView()) ->setName(pht('View As List')) ->setHref($list_uri) - ->setIcon('transcript')); + ->setIcon('fa-list')); $history_uri = $drequest->generateURI( array( 'action' => 'history', )); $view->addAction( id(new PhabricatorActionView()) ->setName(pht('View History')) ->setHref($history_uri) - ->setIcon('history')); + ->setIcon('fa-clock-o')); $browse_uri = $drequest->generateURI( array( 'action' => 'browse', )); $view->addAction( id(new PhabricatorActionView()) ->setName(pht('Browse Content')) ->setHref($browse_uri) - ->setIcon('file')); + ->setIcon('fa-files-o')); return $view; } protected function buildPropertyView( DiffusionRequest $drequest, PhabricatorRepositoryBranch $branch, $total, PhabricatorActionListView $actions) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setActionList($actions); $callsign = $drequest->getRepository()->getCallsign(); $lint_commit = $branch->getLintCommit(); $view->addProperty( pht('Lint Commit'), phutil_tag( 'a', array( 'href' => $drequest->generateURI( array( 'action' => 'commit', 'commit' => $lint_commit, )), ), $drequest->getRepository()->formatCommitName($lint_commit))); $view->addProperty( pht('Total Messages'), pht('%s', new PhutilNumber($total))); return $view; } } diff --git a/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php b/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php index 940c775394..a1b89d1a89 100644 --- a/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php +++ b/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php @@ -1,1121 +1,1121 @@ getRequest(); $viewer = $request->getUser(); $drequest = $this->diffusionRequest; $repository = $drequest->getRepository(); PhabricatorPolicyFilter::requireCapability( $viewer, $repository, PhabricatorPolicyCapability::CAN_EDIT); $is_svn = false; $is_git = false; $is_hg = false; switch ($repository->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $is_git = true; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $is_svn = true; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $is_hg = true; break; } $has_branches = ($is_git || $is_hg); $has_local = $repository->usesLocalWorkingCopy(); $crumbs = $this->buildApplicationCrumbs($is_main = true); $title = pht('Edit %s', $repository->getName()); $header = id(new PHUIHeaderView()) ->setHeader($title); if ($repository->isTracked()) { $header->setStatus('oh-ok', '', pht('Active')); } else { $header->setStatus('policy-noone', '', pht('Inactive')); } $basic_actions = $this->buildBasicActions($repository); $basic_properties = $this->buildBasicProperties($repository, $basic_actions); $policy_actions = $this->buildPolicyActions($repository); $policy_properties = $this->buildPolicyProperties($repository, $policy_actions); $remote_properties = null; if (!$repository->isHosted()) { $remote_properties = $this->buildRemoteProperties( $repository, $this->buildRemoteActions($repository)); } $encoding_actions = $this->buildEncodingActions($repository); $encoding_properties = $this->buildEncodingProperties($repository, $encoding_actions); $hosting_properties = $this->buildHostingProperties( $repository, $this->buildHostingActions($repository)); $branches_properties = null; if ($has_branches) { $branches_properties = $this->buildBranchesProperties( $repository, $this->buildBranchesActions($repository)); } $subversion_properties = null; if ($is_svn) { $subversion_properties = $this->buildSubversionProperties( $repository, $this->buildSubversionActions($repository)); } $local_properties = null; if ($has_local) { $local_properties = $this->buildLocalProperties( $repository, $this->buildLocalActions($repository)); } $actions_properties = $this->buildActionsProperties( $repository, $this->buildActionsActions($repository)); $xactions = id(new PhabricatorRepositoryTransactionQuery()) ->setViewer($viewer) ->withObjectPHIDs(array($repository->getPHID())) ->execute(); $engine = id(new PhabricatorMarkupEngine()) ->setViewer($viewer); foreach ($xactions as $xaction) { if ($xaction->getComment()) { $engine->addObject( $xaction->getComment(), PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT); } } $engine->process(); $xaction_view = id(new PhabricatorApplicationTransactionView()) ->setUser($viewer) ->setObjectPHID($repository->getPHID()) ->setTransactions($xactions) ->setMarkupEngine($engine); $boxes = array(); $boxes[] = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($basic_properties); $boxes[] = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Policies')) ->addPropertyList($policy_properties); $boxes[] = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Hosting')) ->addPropertyList($hosting_properties); if ($repository->canMirror()) { $mirror_actions = $this->buildMirrorActions($repository); $mirror_properties = $this->buildMirrorProperties( $repository, $mirror_actions); $mirrors = id(new PhabricatorRepositoryMirrorQuery()) ->setViewer($viewer) ->withRepositoryPHIDs(array($repository->getPHID())) ->execute(); $mirror_list = $this->buildMirrorList($repository, $mirrors); $boxes[] = id(new PhabricatorAnchorView())->setAnchorName('mirrors'); $boxes[] = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Mirrors')) ->addPropertyList($mirror_properties); $boxes[] = $mirror_list; } if ($remote_properties) { $boxes[] = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Remote')) ->addPropertyList($remote_properties); } if ($local_properties) { $boxes[] = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Local')) ->addPropertyList($local_properties); } $boxes[] = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Text Encoding')) ->addPropertyList($encoding_properties); if ($branches_properties) { $boxes[] = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Branches')) ->addPropertyList($branches_properties); } if ($subversion_properties) { $boxes[] = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Subversion')) ->addPropertyList($subversion_properties); } $boxes[] = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Actions')) ->addPropertyList($actions_properties); return $this->buildApplicationPage( array( $crumbs, $boxes, $xaction_view, ), array( 'title' => $title, 'device' => true, )); } private function buildBasicActions(PhabricatorRepository $repository) { $viewer = $this->getRequest()->getUser(); $view = id(new PhabricatorActionListView()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setUser($viewer); $edit = id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Edit Basic Information')) ->setHref($this->getRepositoryControllerURI($repository, 'edit/basic/')); $view->addAction($edit); $activate = id(new PhabricatorActionView()) ->setHref( $this->getRepositoryControllerURI($repository, 'edit/activate/')) ->setWorkflow(true); if ($repository->isTracked()) { $activate ->setIcon('fa-pause') ->setName(pht('Deactivate Repository')); } else { $activate ->setIcon('fa-play') ->setName(pht('Activate Repository')); } $view->addAction($activate); $view->addAction( id(new PhabricatorActionView()) ->setName(pht('Delete Repository')) ->setIcon('fa-times') ->setHref( $this->getRepositoryControllerURI($repository, 'edit/delete/')) ->setDisabled(true) ->setWorkflow(true)); return $view; } private function buildBasicProperties( PhabricatorRepository $repository, PhabricatorActionListView $actions) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setActionList($actions); $type = PhabricatorRepositoryType::getNameForRepositoryType( $repository->getVersionControlSystem()); $view->addProperty(pht('Type'), $type); $view->addProperty(pht('Callsign'), $repository->getCallsign()); $clone_name = $repository->getDetail('clone-name'); if ($repository->isHosted()) { $view->addProperty( pht('Clone/Checkout As'), $clone_name ? $clone_name.'/' : phutil_tag('em', array(), $repository->getCloneName().'/')); } $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( $repository->getPHID(), PhabricatorEdgeConfig::TYPE_OBJECT_HAS_PROJECT); if ($project_phids) { $this->loadHandles($project_phids); $project_text = $this->renderHandlesForPHIDs($project_phids); } else { $project_text = phutil_tag('em', array(), pht('None')); } $view->addProperty( pht('Projects'), $project_text); $view->addProperty( pht('Status'), $this->buildRepositoryStatus($repository)); $description = $repository->getDetail('description'); $view->addSectionHeader(pht('Description')); if (!strlen($description)) { $description = phutil_tag('em', array(), pht('No description provided.')); } else { $description = PhabricatorMarkupEngine::renderOneObject( $repository, 'description', $viewer); } $view->addTextContent($description); return $view; } private function buildEncodingActions(PhabricatorRepository $repository) { $viewer = $this->getRequest()->getUser(); $view = id(new PhabricatorActionListView()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setUser($viewer); $edit = id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Edit Text Encoding')) ->setHref( $this->getRepositoryControllerURI($repository, 'edit/encoding/')); $view->addAction($edit); return $view; } private function buildEncodingProperties( PhabricatorRepository $repository, PhabricatorActionListView $actions) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setActionList($actions); $encoding = $repository->getDetail('encoding'); if (!$encoding) { $encoding = phutil_tag('em', array(), pht('Use Default (UTF-8)')); } $view->addProperty(pht('Encoding'), $encoding); return $view; } private function buildPolicyActions(PhabricatorRepository $repository) { $viewer = $this->getRequest()->getUser(); $view = id(new PhabricatorActionListView()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setUser($viewer); $edit = id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Edit Policies')) ->setHref( $this->getRepositoryControllerURI($repository, 'edit/policy/')); $view->addAction($edit); return $view; } private function buildPolicyProperties( PhabricatorRepository $repository, PhabricatorActionListView $actions) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setActionList($actions); $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( $viewer, $repository); $view->addProperty( pht('Visible To'), $descriptions[PhabricatorPolicyCapability::CAN_VIEW]); $view->addProperty( pht('Editable By'), $descriptions[PhabricatorPolicyCapability::CAN_EDIT]); $pushable = $repository->isHosted() ? $descriptions[DiffusionCapabilityPush::CAPABILITY] : phutil_tag('em', array(), pht('Not a Hosted Repository')); $view->addProperty(pht('Pushable By'), $pushable); return $view; } private function buildBranchesActions(PhabricatorRepository $repository) { $viewer = $this->getRequest()->getUser(); $view = id(new PhabricatorActionListView()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setUser($viewer); $edit = id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Edit Branches')) ->setHref( $this->getRepositoryControllerURI($repository, 'edit/branches/')); $view->addAction($edit); return $view; } private function buildBranchesProperties( PhabricatorRepository $repository, PhabricatorActionListView $actions) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setActionList($actions); $default_branch = nonempty( $repository->getHumanReadableDetail('default-branch'), phutil_tag('em', array(), $repository->getDefaultBranch())); $view->addProperty(pht('Default Branch'), $default_branch); $track_only = nonempty( $repository->getHumanReadableDetail('branch-filter', array()), phutil_tag('em', array(), pht('Track All Branches'))); $view->addProperty(pht('Track Only'), $track_only); $autoclose_only = nonempty( $repository->getHumanReadableDetail('close-commits-filter', array()), phutil_tag('em', array(), pht('Autoclose On All Branches'))); if ($repository->getDetail('disable-autoclose')) { $autoclose_only = phutil_tag('em', array(), pht('Disabled')); } $view->addProperty(pht('Autoclose Only'), $autoclose_only); return $view; } private function buildSubversionActions(PhabricatorRepository $repository) { $viewer = $this->getRequest()->getUser(); $view = id(new PhabricatorActionListView()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setUser($viewer); $edit = id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Edit Subversion Info')) ->setHref( $this->getRepositoryControllerURI($repository, 'edit/subversion/')); $view->addAction($edit); return $view; } private function buildSubversionProperties( PhabricatorRepository $repository, PhabricatorActionListView $actions) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setActionList($actions); $svn_uuid = nonempty( $repository->getUUID(), phutil_tag('em', array(), pht('Not Configured'))); $view->addProperty(pht('Subversion UUID'), $svn_uuid); $svn_subpath = nonempty( $repository->getHumanReadableDetail('svn-subpath'), phutil_tag('em', array(), pht('Import Entire Repository'))); $view->addProperty(pht('Import Only'), $svn_subpath); return $view; } private function buildActionsActions(PhabricatorRepository $repository) { $viewer = $this->getRequest()->getUser(); $view = id(new PhabricatorActionListView()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setUser($viewer); $edit = id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Edit Actions')) ->setHref( $this->getRepositoryControllerURI($repository, 'edit/actions/')); $view->addAction($edit); return $view; } private function buildActionsProperties( PhabricatorRepository $repository, PhabricatorActionListView $actions) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setActionList($actions); $notify = $repository->getDetail('herald-disabled') ? pht('Off') : pht('On'); $notify = phutil_tag('em', array(), $notify); $view->addProperty(pht('Publish/Notify'), $notify); $autoclose = $repository->getDetail('disable-autoclose') ? pht('Off') : pht('On'); $autoclose = phutil_tag('em', array(), $autoclose); $view->addProperty(pht('Autoclose'), $autoclose); return $view; } private function buildRemoteActions(PhabricatorRepository $repository) { $viewer = $this->getRequest()->getUser(); $view = id(new PhabricatorActionListView()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setUser($viewer); $edit = id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Edit Remote')) ->setHref( $this->getRepositoryControllerURI($repository, 'edit/remote/')); $view->addAction($edit); return $view; } private function buildRemoteProperties( PhabricatorRepository $repository, PhabricatorActionListView $actions) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setActionList($actions); $view->addProperty( pht('Remote URI'), $repository->getHumanReadableDetail('remote-uri')); $credential_phid = $repository->getCredentialPHID(); if ($credential_phid) { $this->loadHandles(array($credential_phid)); $view->addProperty( pht('Credential'), $this->getHandle($credential_phid)->renderLink()); } return $view; } private function buildLocalActions(PhabricatorRepository $repository) { $viewer = $this->getRequest()->getUser(); $view = id(new PhabricatorActionListView()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setUser($viewer); $edit = id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Edit Local')) ->setHref( $this->getRepositoryControllerURI($repository, 'edit/local/')); $view->addAction($edit); return $view; } private function buildLocalProperties( PhabricatorRepository $repository, PhabricatorActionListView $actions) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setActionList($actions); $view->addProperty( pht('Local Path'), $repository->getHumanReadableDetail('local-path')); return $view; } private function buildHostingActions(PhabricatorRepository $repository) { $user = $this->getRequest()->getUser(); $view = id(new PhabricatorActionListView()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setUser($user); $edit = id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Edit Hosting')) ->setHref( $this->getRepositoryControllerURI($repository, 'edit/hosting/')); $view->addAction($edit); if ($repository->canAllowDangerousChanges()) { if ($repository->shouldAllowDangerousChanges()) { $changes = id(new PhabricatorActionView()) ->setIcon('fa-shield') ->setName(pht('Prevent Dangerous Changes')) ->setHref( $this->getRepositoryControllerURI($repository, 'edit/dangerous/')) ->setWorkflow(true); } else { $changes = id(new PhabricatorActionView()) ->setIcon('fa-bullseye') ->setName(pht('Allow Dangerous Changes')) ->setHref( $this->getRepositoryControllerURI($repository, 'edit/dangerous/')) ->setWorkflow(true); } $view->addAction($changes); } return $view; } private function buildHostingProperties( PhabricatorRepository $repository, PhabricatorActionListView $actions) { $user = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($user) ->setActionList($actions); $hosting = $repository->isHosted() ? pht('Hosted on Phabricator') : pht('Hosted Elsewhere'); $view->addProperty(pht('Hosting'), phutil_tag('em', array(), $hosting)); $view->addProperty( pht('Serve over HTTP'), phutil_tag( 'em', array(), PhabricatorRepository::getProtocolAvailabilityName( $repository->getServeOverHTTP()))); $view->addProperty( pht('Serve over SSH'), phutil_tag( 'em', array(), PhabricatorRepository::getProtocolAvailabilityName( $repository->getServeOverSSH()))); if ($repository->canAllowDangerousChanges()) { if ($repository->shouldAllowDangerousChanges()) { $description = pht('Allowed'); } else { $description = pht('Not Allowed'); } $view->addProperty( pht('Dangerous Changes'), $description); } return $view; } private function buildRepositoryStatus( PhabricatorRepository $repository) { $viewer = $this->getRequest()->getUser(); $view = new PHUIStatusListView(); $messages = id(new PhabricatorRepositoryStatusMessage()) ->loadAllWhere('repositoryID = %d', $repository->getID()); $messages = mpull($messages, null, 'getStatusType'); if ($repository->isTracked()) { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('accept-green') ->setTarget(pht('Repository Active'))); } else { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('warning') ->setTarget(pht('Repository Inactive')) ->setNote( pht('Activate this repository to begin or resume import.'))); return $view; } $binaries = array(); $svnlook_check = false; switch ($repository->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $binaries[] = 'git'; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $binaries[] = 'svn'; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $binaries[] = 'hg'; break; } if ($repository->isHosted()) { if ($repository->getServeOverHTTP() != PhabricatorRepository::SERVE_OFF) { switch ($repository->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $binaries[] = 'git-http-backend'; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $binaries[] = 'svnserve'; $binaries[] = 'svnadmin'; $binaries[] = 'svnlook'; $svnlook_check = true; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $binaries[] = 'hg'; break; } } if ($repository->getServeOverSSH() != PhabricatorRepository::SERVE_OFF) { switch ($repository->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $binaries[] = 'git-receive-pack'; $binaries[] = 'git-upload-pack'; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $binaries[] = 'svnserve'; $binaries[] = 'svnadmin'; $binaries[] = 'svnlook'; $svnlook_check = true; break; case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $binaries[] = 'hg'; break; } } } $binaries = array_unique($binaries); foreach ($binaries as $binary) { $where = Filesystem::resolveBinary($binary); if (!$where) { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('warning-red') ->setTarget( pht('Missing Binary %s', phutil_tag('tt', array(), $binary))) ->setNote(pht( "Unable to find this binary in the webserver's PATH. You may ". "need to configure %s.", $this->getEnvConfigLink()))); } else { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('accept-green') ->setTarget( pht('Found Binary %s', phutil_tag('tt', array(), $binary))) ->setNote(phutil_tag('tt', array(), $where))); } } // This gets checked generically above. However, for svn commit hooks, we // need this to be in environment.append-paths because subversion strips // PATH. if ($svnlook_check) { $where = Filesystem::resolveBinary('svnlook'); if ($where) { $path = substr($where, 0, strlen($where) - strlen('svnlook')); $dirs = PhabricatorEnv::getEnvConfig('environment.append-paths'); $in_path = false; foreach ($dirs as $dir) { if (Filesystem::isDescendant($path, $dir)) { $in_path = true; break; } } if (!$in_path) { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('warning-red') ->setTarget( pht('Missing Binary %s', phutil_tag('tt', array(), $binary))) ->setNote(pht( 'Unable to find this binary in `environment.append-paths`. '. 'You need to configure %s and include %s.', $this->getEnvConfigLink(), $path))); } } } $doc_href = PhabricatorEnv::getDocLink('Managing Daemons with phd'); $daemon_instructions = pht( 'Use %s to start daemons. See %s.', phutil_tag('tt', array(), 'bin/phd start'), phutil_tag( 'a', array( 'href' => $doc_href, ), pht('Managing Daemons with phd'))); $pull_daemon = id(new PhabricatorDaemonLogQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) ->withDaemonClasses(array('PhabricatorRepositoryPullLocalDaemon')) ->setLimit(1) ->execute(); if ($pull_daemon) { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('accept-green') ->setTarget(pht('Pull Daemon Running'))); } else { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('warning-red') ->setTarget(pht('Pull Daemon Not Running')) ->setNote($daemon_instructions)); } $task_daemon = id(new PhabricatorDaemonLogQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) ->withDaemonClasses(array('PhabricatorTaskmasterDaemon')) ->setLimit(1) ->execute(); if ($task_daemon) { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('accept-green') ->setTarget(pht('Task Daemon Running'))); } else { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('warning-red') ->setTarget(pht('Task Daemon Not Running')) ->setNote($daemon_instructions)); } if ($repository->usesLocalWorkingCopy()) { $local_parent = dirname($repository->getLocalPath()); if (Filesystem::pathExists($local_parent)) { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('accept-green') ->setTarget(pht('Storage Directory OK')) ->setNote(phutil_tag('tt', array(), $local_parent))); } else { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('warning-red') ->setTarget(pht('No Storage Directory')) ->setNote( pht( 'Storage directory %s does not exist, or is not readable by '. 'the webserver. Create this directory or make it readable.', phutil_tag('tt', array(), $local_parent)))); return $view; } $local_path = $repository->getLocalPath(); $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_INIT); if ($message) { switch ($message->getStatusCode()) { case PhabricatorRepositoryStatusMessage::CODE_ERROR: $view->addItem( id(new PHUIStatusItemView()) ->setIcon('warning-red') ->setTarget(pht('Initialization Error')) ->setNote($message->getParameter('message'))); return $view; case PhabricatorRepositoryStatusMessage::CODE_OKAY: if (Filesystem::pathExists($local_path)) { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('accept-green') ->setTarget(pht('Working Copy OK')) ->setNote(phutil_tag('tt', array(), $local_path))); } else { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('warning-red') ->setTarget(pht('Working Copy Error')) ->setNote( pht( 'Working copy %s has been deleted, or is not '. 'readable by the webserver. Make this directory '. 'readable. If it has been deleted, the daemons should '. 'restore it automatically.', phutil_tag('tt', array(), $local_path)))); return $view; } break; case PhabricatorRepositoryStatusMessage::CODE_WORKING: $view->addItem( id(new PHUIStatusItemView()) ->setIcon('time-green') ->setTarget(pht('Initializing Working Copy')) ->setNote(pht('Daemons are initializing the working copy.'))); return $view; default: $view->addItem( id(new PHUIStatusItemView()) ->setIcon('warning-red') ->setTarget(pht('Unknown Init Status')) ->setNote($message->getStatusCode())); return $view; } } else { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('time-orange') ->setTarget(pht('No Working Copy Yet')) ->setNote( pht('Waiting for daemons to build a working copy.'))); return $view; } } $message = idx($messages, PhabricatorRepositoryStatusMessage::TYPE_FETCH); if ($message) { switch ($message->getStatusCode()) { case PhabricatorRepositoryStatusMessage::CODE_ERROR: $view->addItem( id(new PHUIStatusItemView()) ->setIcon('warning-red') ->setTarget(pht('Update Error')) ->setNote($message->getParameter('message'))); return $view; case PhabricatorRepositoryStatusMessage::CODE_OKAY: $view->addItem( id(new PHUIStatusItemView()) ->setIcon('accept-green') ->setTarget(pht('Updates OK')) ->setNote( pht( 'Last updated %s.', phabricator_datetime($message->getEpoch(), $viewer)))); break; } } else { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('time-orange') ->setTarget(pht('Waiting For Update')) ->setNote( pht('Waiting for daemons to read updates.'))); } if ($repository->isImporting()) { $progress = queryfx_all( $repository->establishConnection('r'), 'SELECT importStatus, count(*) N FROM %T WHERE repositoryID = %d GROUP BY importStatus', id(new PhabricatorRepositoryCommit())->getTableName(), $repository->getID()); $done = 0; $total = 0; foreach ($progress as $row) { $total += $row['N'] * 4; $status = $row['importStatus']; if ($status & PhabricatorRepositoryCommit::IMPORTED_MESSAGE) { $done += $row['N']; } if ($status & PhabricatorRepositoryCommit::IMPORTED_CHANGE) { $done += $row['N']; } if ($status & PhabricatorRepositoryCommit::IMPORTED_OWNERS) { $done += $row['N']; } if ($status & PhabricatorRepositoryCommit::IMPORTED_HERALD) { $done += $row['N']; } } if ($total) { $percentage = 100 * ($done / $total); } else { $percentage = 0; } // Cap this at "99.99%", because it's confusing to users when the actual // fraction is "99.996%" and it rounds up to "100.00%". if ($percentage > 99.99) { $percentage = 99.99; } $percentage = sprintf('%.2f%%', $percentage); $view->addItem( id(new PHUIStatusItemView()) ->setIcon('time-green') ->setTarget(pht('Importing')) ->setNote( pht('%s Complete', $percentage))); } else { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('accept-green') ->setTarget(pht('Fully Imported'))); } if (idx($messages, PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE)) { $view->addItem( id(new PHUIStatusItemView()) ->setIcon('up') ->setTarget(pht('Prioritized')) ->setNote(pht('This repository will be updated soon.'))); } return $view; } private function buildMirrorActions( PhabricatorRepository $repository) { $viewer = $this->getRequest()->getUser(); $mirror_actions = id(new PhabricatorActionListView()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setUser($viewer); $new_mirror_uri = $this->getRepositoryControllerURI( $repository, 'mirror/edit/'); $mirror_actions->addAction( id(new PhabricatorActionView()) ->setName(pht('Add Mirror')) ->setIcon('fa-plus') ->setHref($new_mirror_uri) ->setWorkflow(true)); return $mirror_actions; } private function buildMirrorProperties( PhabricatorRepository $repository, PhabricatorActionListView $actions) { $viewer = $this->getRequest()->getUser(); $mirror_properties = id(new PHUIPropertyListView()) ->setUser($viewer) ->setActionList($actions); $mirror_properties->addProperty( '', phutil_tag( 'em', array(), pht('Automatically push changes into other remotes.'))); return $mirror_properties; } private function buildMirrorList( PhabricatorRepository $repository, array $mirrors) { assert_instances_of($mirrors, 'PhabricatorRepositoryMirror'); $mirror_list = id(new PHUIObjectItemListView()) ->setNoDataString(pht('This repository has no configured mirrors.')); foreach ($mirrors as $mirror) { $item = id(new PHUIObjectItemView()) ->setHeader($mirror->getRemoteURI()); $edit_uri = $this->getRepositoryControllerURI( $repository, 'mirror/edit/'.$mirror->getID().'/'); $delete_uri = $this->getRepositoryControllerURI( $repository, 'mirror/delete/'.$mirror->getID().'/'); $item->addAction( id(new PHUIListItemView()) ->setIcon('fa-pencil') ->setHref($edit_uri) ->setWorkflow(true)); $item->addAction( id(new PHUIListItemView()) - ->setIcon('delete') + ->setIcon('fa-times') ->setHref($delete_uri) ->setWorkflow(true)); $mirror_list->addItem($item); } return $mirror_list; } private function getEnvConfigLink() { $config_href = '/config/edit/environment.append-paths/'; return phutil_tag( 'a', array( 'href' => $config_href, ), 'environment.append-paths'); } } diff --git a/src/applications/drydock/controller/DrydockLeaseViewController.php b/src/applications/drydock/controller/DrydockLeaseViewController.php index cbf83d6120..7075e55128 100644 --- a/src/applications/drydock/controller/DrydockLeaseViewController.php +++ b/src/applications/drydock/controller/DrydockLeaseViewController.php @@ -1,138 +1,138 @@ id = $data['id']; } public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); $lease = id(new DrydockLeaseQuery()) ->setViewer($viewer) ->withIDs(array($this->id)) ->executeOne(); if (!$lease) { return new Aphront404Response(); } $lease_uri = $this->getApplicationURI('lease/'.$lease->getID().'/'); $title = pht('Lease %d', $lease->getID()); $header = id(new PHUIHeaderView()) ->setHeader($title); $actions = $this->buildActionListView($lease); $properties = $this->buildPropertyListView($lease, $actions); $pager = new AphrontPagerView(); $pager->setURI(new PhutilURI($lease_uri), 'offset'); $pager->setOffset($request->getInt('offset')); $logs = id(new DrydockLogQuery()) ->setViewer($viewer) ->withLeaseIDs(array($lease->getID())) ->executeWithOffsetPager($pager); $log_table = $this->buildLogTableView($logs); $log_table->appendChild($pager); $crumbs = $this->buildApplicationCrumbs(); $crumbs->setActionList($actions); $crumbs->addTextCrumb($title, $lease_uri); $object_box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); return $this->buildApplicationPage( array( $crumbs, $object_box, $log_table, ), array( 'device' => true, 'title' => $title, )); } private function buildActionListView(DrydockLease $lease) { $view = id(new PhabricatorActionListView()) ->setUser($this->getRequest()->getUser()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setObject($lease); $id = $lease->getID(); $can_release = ($lease->getStatus() == DrydockLeaseStatus::STATUS_ACTIVE); $view->addAction( id(new PhabricatorActionView()) ->setName(pht('Release Lease')) - ->setIcon('delete') + ->setIcon('fa-times') ->setHref($this->getApplicationURI("/lease/{$id}/release/")) ->setWorkflow(true) ->setDisabled(!$can_release)); return $view; } private function buildPropertyListView( DrydockLease $lease, PhabricatorActionListView $actions) { $view = new PHUIPropertyListView(); $view->setActionList($actions); switch ($lease->getStatus()) { case DrydockLeaseStatus::STATUS_ACTIVE: $status = pht('Active'); break; case DrydockLeaseStatus::STATUS_RELEASED: $status = pht('Released'); break; case DrydockLeaseStatus::STATUS_EXPIRED: $status = pht('Expired'); break; case DrydockLeaseStatus::STATUS_PENDING: $status = pht('Pending'); break; case DrydockLeaseStatus::STATUS_BROKEN: $status = pht('Broken'); break; default: $status = pht('Unknown'); break; } $view->addProperty( pht('Status'), $status); $view->addProperty( pht('Resource Type'), $lease->getResourceType()); $view->addProperty( pht('Resource'), $lease->getResourceID()); $attributes = $lease->getAttributes(); if ($attributes) { $view->addSectionHeader(pht('Attributes')); foreach ($attributes as $key => $value) { $view->addProperty($key, $value); } } return $view; } } diff --git a/src/applications/drydock/controller/DrydockResourceViewController.php b/src/applications/drydock/controller/DrydockResourceViewController.php index e8e7340a88..9ac417bad3 100644 --- a/src/applications/drydock/controller/DrydockResourceViewController.php +++ b/src/applications/drydock/controller/DrydockResourceViewController.php @@ -1,131 +1,131 @@ id = $data['id']; } public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); $resource = id(new DrydockResourceQuery()) ->setViewer($viewer) ->withIDs(array($this->id)) ->executeOne(); if (!$resource) { return new Aphront404Response(); } $title = 'Resource '.$resource->getID().' '.$resource->getName(); $header = id(new PHUIHeaderView()) ->setHeader($title); $actions = $this->buildActionListView($resource); $properties = $this->buildPropertyListView($resource, $actions); $resource_uri = 'resource/'.$resource->getID().'/'; $resource_uri = $this->getApplicationURI($resource_uri); $leases = id(new DrydockLeaseQuery()) ->setViewer($viewer) ->withResourceIDs(array($resource->getID())) ->execute(); $lease_list = $this->buildLeaseListView($leases); $lease_list->setNoDataString(pht('This resource has no leases.')); $pager = new AphrontPagerView(); $pager->setURI(new PhutilURI($resource_uri), 'offset'); $pager->setOffset($request->getInt('offset')); $logs = id(new DrydockLogQuery()) ->setViewer($viewer) ->withResourceIDs(array($resource->getID())) ->executeWithOffsetPager($pager); $log_table = $this->buildLogTableView($logs); $log_table->appendChild($pager); $crumbs = $this->buildApplicationCrumbs(); $crumbs->setActionList($actions); $crumbs->addTextCrumb(pht('Resource %d', $resource->getID())); $object_box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); return $this->buildApplicationPage( array( $crumbs, $object_box, $lease_list, $log_table, ), array( 'device' => true, 'title' => $title, )); } private function buildActionListView(DrydockResource $resource) { $view = id(new PhabricatorActionListView()) ->setUser($this->getRequest()->getUser()) ->setObjectURI($this->getRequest()->getRequestURI()) ->setObject($resource); $can_close = ($resource->getStatus() == DrydockResourceStatus::STATUS_OPEN); $uri = '/resource/'.$resource->getID().'/close/'; $uri = $this->getApplicationURI($uri); $view->addAction( id(new PhabricatorActionView()) ->setHref($uri) ->setName(pht('Close Resource')) - ->setIcon('delete') + ->setIcon('fa-times') ->setWorkflow(true) ->setDisabled(!$can_close)); return $view; } private function buildPropertyListView( DrydockResource $resource, PhabricatorActionListView $actions) { $view = new PHUIPropertyListView(); $view->setActionList($actions); $status = $resource->getStatus(); $status = DrydockResourceStatus::getNameForStatus($status); $view->addProperty( pht('Status'), $status); $view->addProperty( pht('Resource Type'), $resource->getType()); // TODO: Load handle. $view->addProperty( pht('Blueprint'), $resource->getBlueprintPHID()); $attributes = $resource->getAttributes(); if ($attributes) { $view->addSectionHeader(pht('Attributes')); foreach ($attributes as $key => $value) { $view->addProperty($key, $value); } } return $view; } } diff --git a/src/applications/files/controller/PhabricatorFileInfoController.php b/src/applications/files/controller/PhabricatorFileInfoController.php index 486da7774d..6f6df0f65f 100644 --- a/src/applications/files/controller/PhabricatorFileInfoController.php +++ b/src/applications/files/controller/PhabricatorFileInfoController.php @@ -1,270 +1,270 @@ phid = $data['phid']; } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $file = id(new PhabricatorFileQuery()) ->setViewer($user) ->withPHIDs(array($this->phid)) ->executeOne(); if (!$file) { return new Aphront404Response(); } $phid = $file->getPHID(); $xactions = id(new PhabricatorFileTransactionQuery()) ->setViewer($user) ->withObjectPHIDs(array($phid)) ->execute(); $handle_phids = array_merge( array($file->getAuthorPHID()), $file->getObjectPHIDs()); $this->loadHandles($handle_phids); $header = id(new PHUIHeaderView()) ->setUser($user) ->setPolicyObject($file) ->setHeader($file->getName()); $ttl = $file->getTTL(); if ($ttl !== null) { $ttl_tag = id(new PHUITagView()) ->setType(PHUITagView::TYPE_OBJECT) ->setName(pht("Temporary")); $header->addTag($ttl_tag); } $actions = $this->buildActionView($file); $timeline = $this->buildTransactionView($file, $xactions); $crumbs = $this->buildApplicationCrumbs(); $crumbs->setActionList($actions); $crumbs->addTextCrumb( 'F'.$file->getID(), $this->getApplicationURI("/info/{$phid}/")); $object_box = id(new PHUIObjectBoxView()) ->setHeader($header); $this->buildPropertyViews($object_box, $file, $actions); return $this->buildApplicationPage( array( $crumbs, $object_box, $timeline ), array( 'title' => $file->getName(), 'device' => true, 'pageObjects' => array($file->getPHID()), )); } private function buildTransactionView( PhabricatorFile $file, array $xactions) { $user = $this->getRequest()->getUser(); $engine = id(new PhabricatorMarkupEngine()) ->setViewer($user); foreach ($xactions as $xaction) { if ($xaction->getComment()) { $engine->addObject( $xaction->getComment(), PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT); } } $engine->process(); $timeline = id(new PhabricatorApplicationTransactionView()) ->setUser($user) ->setObjectPHID($file->getPHID()) ->setTransactions($xactions) ->setMarkupEngine($engine); $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); $add_comment_header = $is_serious ? pht('Add Comment') : pht('Question File Integrity'); $draft = PhabricatorDraft::newFromUserAndKey($user, $file->getPHID()); $add_comment_form = id(new PhabricatorApplicationTransactionCommentView()) ->setUser($user) ->setObjectPHID($file->getPHID()) ->setDraft($draft) ->setHeaderText($add_comment_header) ->setAction($this->getApplicationURI('/comment/'.$file->getID().'/')) ->setSubmitButtonName(pht('Add Comment')); return array( $timeline, $add_comment_form); } private function buildActionView(PhabricatorFile $file) { $request = $this->getRequest(); $user = $request->getUser(); $id = $file->getID(); $view = id(new PhabricatorActionListView()) ->setUser($user) ->setObjectURI($this->getRequest()->getRequestURI()) ->setObject($file); if ($file->isViewableInBrowser()) { $view->addAction( id(new PhabricatorActionView()) ->setName(pht('View File')) - ->setIcon('preview') + ->setIcon('fa-file-o') ->setHref($file->getViewURI())); } else { $view->addAction( id(new PhabricatorActionView()) ->setUser($user) ->setRenderAsForm(true) ->setDownload(true) ->setName(pht('Download File')) - ->setIcon('download') + ->setIcon('fa-download') ->setHref($file->getViewURI())); } $view->addAction( id(new PhabricatorActionView()) ->setName(pht('Delete File')) - ->setIcon('delete') + ->setIcon('fa-times') ->setHref($this->getApplicationURI("/delete/{$id}/")) ->setWorkflow(true)); return $view; } private function buildPropertyViews( PHUIObjectBoxView $box, PhabricatorFile $file, PhabricatorActionListView $actions) { $request = $this->getRequest(); $user = $request->getUser(); $properties = id(new PHUIPropertyListView()); $properties->setActionList($actions); $box->addPropertyList($properties, pht('Details')); if ($file->getAuthorPHID()) { $properties->addProperty( pht('Author'), $this->getHandle($file->getAuthorPHID())->renderLink()); } $properties->addProperty( pht('Created'), phabricator_datetime($file->getDateCreated(), $user)); $finfo = id(new PHUIPropertyListView()); $box->addPropertyList($finfo, pht('File Info')); $finfo->addProperty( pht('Size'), phabricator_format_bytes($file->getByteSize())); $finfo->addProperty( pht('Mime Type'), $file->getMimeType()); $width = $file->getImageWidth(); if ($width) { $finfo->addProperty( pht('Width'), pht('%s px', new PhutilNumber($width))); } $height = $file->getImageHeight(); if ($height) { $finfo->addProperty( pht('Height'), pht('%s px', new PhutilNumber($height))); } $storage_properties = new PHUIPropertyListView(); $box->addPropertyList($storage_properties, pht('Storage')); $storage_properties->addProperty( pht('Engine'), $file->getStorageEngine()); $storage_properties->addProperty( pht('Format'), $file->getStorageFormat()); $storage_properties->addProperty( pht('Handle'), $file->getStorageHandle()); $phids = $file->getObjectPHIDs(); if ($phids) { $attached = new PHUIPropertyListView(); $box->addPropertyList($attached, pht('Attached')); $attached->addProperty( pht('Attached To'), $this->renderHandlesForPHIDs($phids)); } if ($file->isViewableImage()) { $image = phutil_tag( 'img', array( 'src' => $file->getViewURI(), 'class' => 'phui-property-list-image', )); $linked_image = phutil_tag( 'a', array( 'href' => $file->getViewURI(), ), $image); $media = id(new PHUIPropertyListView()) ->addImageContent($linked_image); $box->addPropertyList($media); } else if ($file->isAudio()) { $audio = phutil_tag( 'audio', array( 'controls' => 'controls', 'class' => 'phui-property-list-audio', ), phutil_tag( 'source', array( 'src' => $file->getViewURI(), 'type' => $file->getMimeType(), ))); $media = id(new PHUIPropertyListView()) ->addImageContent($audio); $box->addPropertyList($media); } } } diff --git a/src/applications/harbormaster/controller/HarbormasterBuildViewController.php b/src/applications/harbormaster/controller/HarbormasterBuildViewController.php index 0a4a65fc23..f3a16b5c7d 100644 --- a/src/applications/harbormaster/controller/HarbormasterBuildViewController.php +++ b/src/applications/harbormaster/controller/HarbormasterBuildViewController.php @@ -1,366 +1,366 @@ id = $data['id']; } public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); $id = $this->id; $build = id(new HarbormasterBuildQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$build) { return new Aphront404Response(); } $title = pht("Build %d", $id); $header = id(new PHUIHeaderView()) ->setHeader($title) ->setUser($viewer) ->setPolicyObject($build); if ($build->isRestarting()) { $header->setStatus('warning', 'red', pht('Restarting')); } else if ($build->isStopping()) { $header->setStatus('warning', 'red', pht('Stopping')); } else if ($build->isResuming()) { $header->setStatus('warning', 'red', pht('Resuming')); } $box = id(new PHUIObjectBoxView()) ->setHeader($header); $actions = $this->buildActionList($build); $this->buildPropertyLists($box, $build, $actions); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb( $build->getBuildable()->getMonogram(), '/'.$build->getBuildable()->getMonogram()); $crumbs->addTextCrumb($title); $build_targets = id(new HarbormasterBuildTargetQuery()) ->setViewer($viewer) ->withBuildPHIDs(array($build->getPHID())) ->execute(); if ($build_targets) { $messages = id(new HarbormasterBuildMessageQuery()) ->setViewer($viewer) ->withBuildTargetPHIDs(mpull($build_targets, 'getPHID')) ->execute(); $messages = mgroup($messages, 'getBuildTargetPHID'); } else { $messages = array(); } $targets = array(); foreach ($build_targets as $build_target) { $header = id(new PHUIHeaderView()) ->setHeader(pht( 'Build Target %d (%s)', $build_target->getID(), $build_target->getImplementation()->getName())) ->setUser($viewer); $properties = new PHUIPropertyListView(); $details = $build_target->getDetails(); if ($details) { $properties->addSectionHeader(pht('Configuration Details')); foreach ($details as $key => $value) { $properties->addProperty($key, $value); } } $variables = $build_target->getVariables(); if ($variables) { $properties->addSectionHeader(pht('Variables')); foreach ($variables as $key => $value) { $properties->addProperty($key, $value); } } $targets[] = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); $build_messages = idx($messages, $build_target->getPHID(), array()); $targets[] = $this->buildMessages($build_messages); $targets[] = $this->buildArtifacts($build_target); $targets[] = $this->buildLog($build, $build_target); } return $this->buildApplicationPage( array( $crumbs, $box, $targets ), array( 'title' => $title, 'device' => true, )); } private function buildArtifacts(HarbormasterBuildTarget $build_target) { $request = $this->getRequest(); $viewer = $request->getUser(); $artifacts = id(new HarbormasterBuildArtifactQuery()) ->setViewer($viewer) ->withBuildTargetPHIDs(array($build_target->getPHID())) ->execute(); if (count($artifacts) === 0) { return null; } $list = new PHUIObjectItemListView(); foreach ($artifacts as $artifact) { $list->addItem($artifact->getObjectItemView($viewer)); } $header = id(new PHUIHeaderView()) ->setHeader(pht('Build Artifacts')) ->setUser($viewer); $box = id(new PHUIObjectBoxView()) ->setHeader($header); return array($box, $list); } private function buildLog( HarbormasterBuild $build, HarbormasterBuildTarget $build_target) { $request = $this->getRequest(); $viewer = $request->getUser(); $limit = $request->getInt('l', 25); $logs = id(new HarbormasterBuildLogQuery()) ->setViewer($viewer) ->withBuildTargetPHIDs(array($build_target->getPHID())) ->execute(); $log_boxes = array(); foreach ($logs as $log) { $start = 1; $lines = preg_split("/\r\n|\r|\n/", $log->getLogText()); if ($limit !== 0) { $start = count($lines) - $limit; if ($start >= 1) { $lines = array_slice($lines, -$limit, $limit); } else { $start = 1; } } $log_view = new ShellLogView(); $log_view->setLines($lines); $log_view->setStart($start); $header = id(new PHUIHeaderView()) ->setHeader(pht( 'Build Log %d (%s - %s)', $log->getID(), $log->getLogSource(), $log->getLogType())) ->setSubheader($this->createLogHeader($build, $log)) ->setUser($viewer); $log_boxes[] = id(new PHUIObjectBoxView()) ->setHeader($header) ->setForm($log_view); } return $log_boxes; } private function createLogHeader($build, $log) { $request = $this->getRequest(); $limit = $request->getInt('l', 25); $lines_25 = $this->getApplicationURI('/build/'.$build->getID().'/?l=25'); $lines_50 = $this->getApplicationURI('/build/'.$build->getID().'/?l=50'); $lines_100 = $this->getApplicationURI('/build/'.$build->getID().'/?l=100'); $lines_0 = $this->getApplicationURI('/build/'.$build->getID().'/?l=0'); $link_25 = phutil_tag('a', array('href' => $lines_25), pht('25')); $link_50 = phutil_tag('a', array('href' => $lines_50), pht('50')); $link_100 = phutil_tag('a', array('href' => $lines_100), pht('100')); $link_0 = phutil_tag('a', array('href' => $lines_0), pht('Unlimited')); if ($limit === 25) { $link_25 = phutil_tag('strong', array(), $link_25); } else if ($limit === 50) { $link_50 = phutil_tag('strong', array(), $link_50); } else if ($limit === 100) { $link_100 = phutil_tag('strong', array(), $link_100); } else if ($limit === 0) { $link_0 = phutil_tag('strong', array(), $link_0); } return phutil_tag( 'span', array(), array( $link_25, ' - ', $link_50, ' - ', $link_100, ' - ', $link_0, ' Lines')); } private function buildActionList(HarbormasterBuild $build) { $request = $this->getRequest(); $viewer = $request->getUser(); $id = $build->getID(); $list = id(new PhabricatorActionListView()) ->setUser($viewer) ->setObject($build) ->setObjectURI("/build/{$id}"); $can_restart = $build->canRestartBuild(); $can_stop = $build->canStopBuild(); $can_resume = $build->canResumeBuild(); $list->addAction( id(new PhabricatorActionView()) ->setName(pht('Restart Build')) - ->setIcon('backward') + ->setIcon('fa-backward') ->setHref($this->getApplicationURI('/build/restart/'.$id.'/')) ->setDisabled(!$can_restart) ->setWorkflow(true)); $list->addAction( id(new PhabricatorActionView()) ->setName(pht('Stop Build')) - ->setIcon('stop') + ->setIcon('fa-stop') ->setHref($this->getApplicationURI('/build/stop/'.$id.'/')) ->setDisabled(!$can_stop) ->setWorkflow(true)); $list->addAction( id(new PhabricatorActionView()) ->setName(pht('Resume Build')) - ->setIcon('play') + ->setIcon('fa-play') ->setHref($this->getApplicationURI('/build/resume/'.$id.'/')) ->setDisabled(!$can_resume) ->setWorkflow(true)); return $list; } private function buildPropertyLists( PHUIObjectBoxView $box, HarbormasterBuild $build, PhabricatorActionListView $actions) { $request = $this->getRequest(); $viewer = $request->getUser(); $properties = id(new PHUIPropertyListView()) ->setUser($viewer) ->setObject($build) ->setActionList($actions); $box->addPropertyList($properties); $properties->addProperty( pht('Status'), $this->getStatus($build)); $handles = id(new PhabricatorHandleQuery()) ->setViewer($viewer) ->withPHIDs(array( $build->getBuildablePHID(), $build->getBuildPlanPHID())) ->execute(); $properties->addProperty( pht('Buildable'), $handles[$build->getBuildablePHID()]->renderLink()); $properties->addProperty( pht('Build Plan'), $handles[$build->getBuildPlanPHID()]->renderLink()); } private function getStatus(HarbormasterBuild $build) { if ($build->isStopping()) { return pht('Stopping'); } return HarbormasterBuild::getBuildStatusName($build->getBuildStatus()); } private function buildMessages(array $messages) { $viewer = $this->getRequest()->getUser(); if ($messages) { $handles = id(new PhabricatorHandleQuery()) ->setViewer($viewer) ->withPHIDs(mpull($messages, 'getAuthorPHID')) ->execute(); } else { $handles = array(); } $rows = array(); foreach ($messages as $message) { $rows[] = array( $message->getID(), $handles[$message->getAuthorPHID()]->renderLink(), $message->getType(), $message->getIsConsumed() ? pht('Consumed') : null, phabricator_datetime($message->getDateCreated(), $viewer), ); } $table = new AphrontTableView($rows); $table->setNoDataString(pht('No messages for this build target.')); $table->setHeaders( array( pht('ID'), pht('From'), pht('Type'), pht('Consumed'), pht('Received'), )); $table->setColumnClasses( array( '', '', 'wide', '', 'date', )); $box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Build Target Messages')) ->appendChild($table); return $box; } } diff --git a/src/applications/harbormaster/controller/HarbormasterBuildableViewController.php b/src/applications/harbormaster/controller/HarbormasterBuildableViewController.php index dcc68da6f4..ac82071ee1 100644 --- a/src/applications/harbormaster/controller/HarbormasterBuildableViewController.php +++ b/src/applications/harbormaster/controller/HarbormasterBuildableViewController.php @@ -1,297 +1,297 @@ id = $data['id']; } public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); $id = $this->id; $buildable = id(new HarbormasterBuildableQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needBuildableHandles(true) ->needContainerHandles(true) ->executeOne(); if (!$buildable) { return new Aphront404Response(); } // Pull builds and build targets. $builds = id(new HarbormasterBuildQuery()) ->setViewer($viewer) ->withBuildablePHIDs(array($buildable->getPHID())) ->needBuildTargets(true) ->execute(); $buildable->attachBuilds($builds); $build_list = $this->buildBuildList($buildable); $title = pht("Buildable %d", $id); $header = id(new PHUIHeaderView()) ->setHeader($title) ->setUser($viewer) ->setPolicyObject($buildable); $box = id(new PHUIObjectBoxView()) ->setHeader($header); $actions = $this->buildActionList($buildable); $this->buildPropertyLists($box, $buildable, $actions); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb("B{$id}"); return $this->buildApplicationPage( array( $crumbs, $box, $build_list, ), array( 'title' => $title, 'device' => true, )); } private function buildActionList(HarbormasterBuildable $buildable) { $request = $this->getRequest(); $viewer = $request->getUser(); $id = $buildable->getID(); $list = id(new PhabricatorActionListView()) ->setUser($viewer) ->setObject($buildable) ->setObjectURI($buildable->getMonogram()); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $buildable, PhabricatorPolicyCapability::CAN_EDIT); $can_restart = false; $can_resume = false; $can_stop = false; foreach ($buildable->getBuilds() as $build) { if ($build->canRestartBuild()) { $can_restart = true; } if ($build->canResumeBuild()) { $can_resume = true; } if ($build->canStopBuild()) { $can_stop = true; } } $restart_uri = "buildable/{$id}/restart/"; $stop_uri = "buildable/{$id}/stop/"; $resume_uri = "buildable/{$id}/resume/"; $list->addAction( id(new PhabricatorActionView()) - ->setIcon('backward') + ->setIcon('fa-backward') ->setName(pht('Restart All Builds')) ->setHref($this->getApplicationURI($restart_uri)) ->setWorkflow(true) ->setDisabled(!$can_restart || !$can_edit)); $list->addAction( id(new PhabricatorActionView()) - ->setIcon('stop') + ->setIcon('fa-stop') ->setName(pht('Stop All Builds')) ->setHref($this->getApplicationURI($stop_uri)) ->setWorkflow(true) ->setDisabled(!$can_stop || !$can_edit)); $list->addAction( id(new PhabricatorActionView()) - ->setIcon('play') + ->setIcon('fa-play') ->setName(pht('Resume All Builds')) ->setHref($this->getApplicationURI($resume_uri)) ->setWorkflow(true) ->setDisabled(!$can_resume || !$can_edit)); return $list; } private function buildPropertyLists( PHUIObjectBoxView $box, HarbormasterBuildable $buildable, PhabricatorActionListView $actions) { $request = $this->getRequest(); $viewer = $request->getUser(); $properties = id(new PHUIPropertyListView()) ->setUser($viewer) ->setObject($buildable) ->setActionList($actions); $box->addPropertyList($properties); $properties->addProperty( pht('Buildable'), $buildable->getBuildableHandle()->renderLink()); if ($buildable->getContainerHandle() !== null) { $properties->addProperty( pht('Container'), $buildable->getContainerHandle()->renderLink()); } $properties->addProperty( pht('Origin'), $buildable->getIsManualBuildable() ? pht('Manual Buildable') : pht('Automatic Buildable')); } private function buildBuildList(HarbormasterBuildable $buildable) { $viewer = $this->getRequest()->getUser(); $build_list = id(new PHUIObjectItemListView()) ->setUser($viewer); foreach ($buildable->getBuilds() as $build) { $view_uri = $this->getApplicationURI('/build/'.$build->getID().'/'); $item = id(new PHUIObjectItemView()) ->setObjectName(pht('Build %d', $build->getID())) ->setHeader($build->getName()) ->setHref($view_uri); $status = $build->getBuildStatus(); switch ($status) { case HarbormasterBuild::STATUS_INACTIVE: $item->setBarColor('grey'); break; case HarbormasterBuild::STATUS_PENDING: $item->setBarColor('blue'); break; case HarbormasterBuild::STATUS_BUILDING: $item->setBarColor('yellow'); break; case HarbormasterBuild::STATUS_PASSED: $item->setBarColor('green'); break; case HarbormasterBuild::STATUS_FAILED: $item->setBarColor('red'); break; case HarbormasterBuild::STATUS_ERROR: $item->setBarColor('red'); break; case HarbormasterBuild::STATUS_STOPPED: $item->setBarColor('black'); break; } $item->addAttribute(HarbormasterBuild::getBuildStatusName($status)); if ($build->isRestarting()) { - $item->addIcon('backward', pht('Restarting')); + $item->addIcon('fa-backward', pht('Restarting')); } else if ($build->isStopping()) { - $item->addIcon('stop', pht('Stopping')); + $item->addIcon('fa-stop', pht('Stopping')); } else if ($build->isResuming()) { - $item->addIcon('play', pht('Resuming')); + $item->addIcon('fa-play', pht('Resuming')); } $build_id = $build->getID(); $restart_uri = "build/restart/{$build_id}/buildable/"; $resume_uri = "build/resume/{$build_id}/buildable/"; $stop_uri = "build/stop/{$build_id}/buildable/"; $item->addAction( id(new PHUIListItemView()) - ->setIcon('backward') + ->setIcon('fa-backward') ->setName(pht('Restart')) ->setHref($this->getApplicationURI($restart_uri)) ->setWorkflow(true) ->setDisabled(!$build->canRestartBuild())); if ($build->canResumeBuild()) { $item->addAction( id(new PHUIListItemView()) - ->setIcon('play') + ->setIcon('fa-play') ->setName(pht('Resume')) ->setHref($this->getApplicationURI($resume_uri)) ->setWorkflow(true)); } else { $item->addAction( id(new PHUIListItemView()) - ->setIcon('stop') + ->setIcon('fa-stop') ->setName(pht('Stop')) ->setHref($this->getApplicationURI($stop_uri)) ->setWorkflow(true) ->setDisabled(!$build->canStopBuild())); } $targets = $build->getBuildTargets(); if ($targets) { $target_list = id(new PHUIStatusListView()); foreach ($targets as $target) { switch ($target->getTargetStatus()) { case HarbormasterBuildTarget::STATUS_PENDING: $icon = 'time-green'; $status_name = pht('Pending'); break; case HarbormasterBuildTarget::STATUS_BUILDING: $icon = 'right-green'; $status_name = pht('Building'); break; case HarbormasterBuildTarget::STATUS_WAITING: $icon = 'time-orange'; $status_name = pht('Waiting'); break; case HarbormasterBuildTarget::STATUS_PASSED: $icon = 'accept-green'; $status_name = pht('Passed'); break; case HarbormasterBuildTarget::STATUS_FAILED: $icon = 'reject-red'; $status_name = pht('Failed'); break; default: $icon = 'question'; $status_name = pht('Unknown'); break; } try { $impl = $target->getImplementation(); $name = $impl->getName(); } catch (Exception $ex) { $name = $target->getClassName(); } $target_list->addItem( id(new PHUIStatusItemView()) ->setIcon($icon, $status_name) ->setTarget(pht('Target %d', $target->getID())) ->setNote($name)); } $target_box = id(new PHUIBoxView()) ->addPadding(PHUI::PADDING_SMALL) ->appendChild($target_list); $item->appendChild($target_box); } $build_list->addItem($item); } return $build_list; } } diff --git a/src/applications/herald/query/HeraldRuleSearchEngine.php b/src/applications/herald/query/HeraldRuleSearchEngine.php index 1150c60c59..5f912253d1 100644 --- a/src/applications/herald/query/HeraldRuleSearchEngine.php +++ b/src/applications/herald/query/HeraldRuleSearchEngine.php @@ -1,216 +1,216 @@ setParameter( 'authorPHIDs', $this->readUsersFromRequest($request, 'authors')); $saved->setParameter('contentType', $request->getStr('contentType')); $saved->setParameter('ruleType', $request->getStr('ruleType')); $saved->setParameter( 'disabled', $this->readBoolFromRequest($request, 'disabled')); return $saved; } public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { $query = id(new HeraldRuleQuery()); $author_phids = $saved->getParameter('authorPHIDs'); if ($author_phids) { $query->withAuthorPHIDs($author_phids); } $content_type = $saved->getParameter('contentType'); $content_type = idx($this->getContentTypeValues(), $content_type); if ($content_type) { $query->withContentTypes(array($content_type)); } $rule_type = $saved->getParameter('ruleType'); $rule_type = idx($this->getRuleTypeValues(), $rule_type); if ($rule_type) { $query->withRuleTypes(array($rule_type)); } $disabled = $saved->getParameter('disabled'); if ($disabled !== null) { $query->withDisabled($disabled); } return $query; } public function buildSearchForm( AphrontFormView $form, PhabricatorSavedQuery $saved_query) { $phids = $saved_query->getParameter('authorPHIDs', array()); $author_handles = id(new PhabricatorHandleQuery()) ->setViewer($this->requireViewer()) ->withPHIDs($phids) ->execute(); $content_type = $saved_query->getParameter('contentType'); $rule_type = $saved_query->getParameter('ruleType'); $form ->appendChild( id(new AphrontFormTokenizerControl()) ->setDatasource('/typeahead/common/users/') ->setName('authors') ->setLabel(pht('Authors')) ->setValue($author_handles)) ->appendChild( id(new AphrontFormSelectControl()) ->setName('contentType') ->setLabel(pht('Content Type')) ->setValue($content_type) ->setOptions($this->getContentTypeOptions())) ->appendChild( id(new AphrontFormSelectControl()) ->setName('ruleType') ->setLabel(pht('Rule Type')) ->setValue($rule_type) ->setOptions($this->getRuleTypeOptions())) ->appendChild( id(new AphrontFormSelectControl()) ->setName('disabled') ->setLabel(pht('Rule Status')) ->setValue($this->getBoolFromQuery($saved_query, 'disabled')) ->setOptions( array( '' => pht('Show Enabled and Disabled Rules'), 'false' => pht('Show Only Enabled Rules'), 'true' => pht('Show Only Disabled Rules'), ))); } protected function getURI($path) { return '/herald/'.$path; } public function getBuiltinQueryNames() { $names = array(); if ($this->requireViewer()->isLoggedIn()) { $names['authored'] = pht('Authored'); } $names['active'] = pht('Active'); $names['all'] = pht('All'); return $names; } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); $viewer_phid = $this->requireViewer()->getPHID(); switch ($query_key) { case 'all': return $query; case 'active': return $query->setParameter('disabled', false); case 'authored': return $query ->setParameter('authorPHIDs', array($viewer_phid)) ->setParameter('disabled', false); } return parent::buildSavedQueryFromBuiltin($query_key); } private function getContentTypeOptions() { return array( '' => pht('(All Content Types)'), ) + HeraldAdapter::getEnabledAdapterMap($this->requireViewer()); } private function getContentTypeValues() { return array_fuse( array_keys( HeraldAdapter::getEnabledAdapterMap($this->requireViewer()))); } private function getRuleTypeOptions() { return array( '' => pht('(All Rule Types)'), ) + HeraldRuleTypeConfig::getRuleTypeMap(); } private function getRuleTypeValues() { return array_fuse(array_keys(HeraldRuleTypeConfig::getRuleTypeMap())); } protected function getRequiredHandlePHIDsForResultList( array $rules, PhabricatorSavedQuery $query) { return mpull($rules, 'getAuthorPHID'); } protected function renderResultList( array $rules, PhabricatorSavedQuery $query, array $handles) { assert_instances_of($rules, 'HeraldRule'); $viewer = $this->requireViewer(); $content_type_map = HeraldAdapter::getEnabledAdapterMap($viewer); $list = id(new PHUIObjectItemListView()) ->setUser($viewer) ->setCards(true); foreach ($rules as $rule) { $id = $rule->getID(); $item = id(new PHUIObjectItemView()) ->setObjectName("H{$id}") ->setHeader($rule->getName()) ->setHref($this->getApplicationURI("rule/{$id}/")); if ($rule->isPersonalRule()) { - $item->addIcon('user', pht('Personal Rule')); + $item->addIcon('fa-user', pht('Personal Rule')); $item->addByline( pht( 'Authored by %s', $handles[$rule->getAuthorPHID()]->renderLink())); } else { - $item->addIcon('world', pht('Global Rule')); + $item->addIcon('fa-globe', pht('Global Rule')); } if ($rule->getIsDisabled()) { $item->setDisabled(true); - $item->addIcon('disable-grey', pht('Disabled')); + $item->addIcon('fa-lock grey', pht('Disabled')); } $item->addAction( id(new PHUIListItemView()) ->setHref($this->getApplicationURI("history/{$id}/")) - ->setIcon('transcript') + ->setIcon('fa-file-text-o') ->setName(pht('Edit Log'))); $content_type_name = idx($content_type_map, $rule->getContentType()); $item->addAttribute(pht('Affects: %s', $content_type_name)); $list->addItem($item); } return $list; } } diff --git a/src/applications/phame/controller/post/PhamePostViewController.php b/src/applications/phame/controller/post/PhamePostViewController.php index 7c07c7050e..80184735c7 100644 --- a/src/applications/phame/controller/post/PhamePostViewController.php +++ b/src/applications/phame/controller/post/PhamePostViewController.php @@ -1,207 +1,207 @@ id = $data['id']; } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $post = id(new PhamePostQuery()) ->setViewer($user) ->withIDs(array($this->id)) ->executeOne(); if (!$post) { return new Aphront404Response(); } $nav = $this->renderSideNavFilterView(); $this->loadHandles( array( $post->getBlogPHID(), $post->getBloggerPHID(), )); $actions = $this->renderActions($post, $user); $properties = $this->renderProperties($post, $user, $actions); $crumbs = $this->buildApplicationCrumbs(); $crumbs->setActionList($actions); $crumbs->addTextCrumb( $post->getTitle(), $this->getApplicationURI('post/view/'.$post->getID().'/')); $nav->appendChild($crumbs); $header = id(new PHUIHeaderView()) ->setHeader($post->getTitle()) ->setUser($user) ->setPolicyObject($post); $object_box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); if ($post->isDraft()) { $object_box->appendChild( id(new AphrontErrorView()) ->setSeverity(AphrontErrorView::SEVERITY_NOTICE) ->setTitle(pht('Draft Post')) ->appendChild( pht('Only you can see this draft until you publish it. '. 'Use "Preview / Publish" to publish this post.'))); } if (!$post->getBlog()) { $object_box->appendChild( id(new AphrontErrorView()) ->setSeverity(AphrontErrorView::SEVERITY_WARNING) ->setTitle(pht('Not On A Blog')) ->appendChild( pht('This post is not associated with a blog (the blog may have '. 'been deleted). Use "Move Post" to move it to a new blog.'))); } $nav->appendChild( array( $object_box, )); return $this->buildApplicationPage( $nav, array( 'title' => $post->getTitle(), 'device' => true, )); } private function renderActions( PhamePost $post, PhabricatorUser $user) { $actions = id(new PhabricatorActionListView()) ->setObject($post) ->setObjectURI($this->getRequest()->getRequestURI()) ->setUser($user); $can_edit = PhabricatorPolicyFilter::hasCapability( $user, $post, PhabricatorPolicyCapability::CAN_EDIT); $id = $post->getID(); $actions->addAction( id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setHref($this->getApplicationURI('post/edit/'.$id.'/')) ->setName(pht('Edit Post')) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); $actions->addAction( id(new PhabricatorActionView()) ->setIcon('fa-arrows') ->setHref($this->getApplicationURI('post/move/'.$id.'/')) ->setName(pht('Move Post')) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); if ($post->isDraft()) { $actions->addAction( id(new PhabricatorActionView()) - ->setIcon('preview') + ->setIcon('fa-eye') ->setHref($this->getApplicationURI('post/publish/'.$id.'/')) ->setName(pht('Preview / Publish'))); } else { $actions->addAction( id(new PhabricatorActionView()) - ->setIcon('unpublish') + ->setIcon('fa-eye-slash') ->setHref($this->getApplicationURI('post/unpublish/'.$id.'/')) ->setName(pht('Unpublish')) ->setWorkflow(true)); } $actions->addAction( id(new PhabricatorActionView()) - ->setIcon('delete') + ->setIcon('fa-times') ->setHref($this->getApplicationURI('post/delete/'.$id.'/')) ->setName(pht('Delete Post')) ->setDisabled(!$can_edit) ->setWorkflow(true)); $blog = $post->getBlog(); $can_view_live = $blog && !$post->isDraft(); if ($can_view_live) { $live_uri = $blog->getLiveURI($post); } else { $live_uri = 'post/notlive/'.$post->getID().'/'; $live_uri = $this->getApplicationURI($live_uri); } $actions->addAction( id(new PhabricatorActionView()) ->setUser($user) - ->setIcon('world') + ->setIcon('fa-globe') ->setHref($live_uri) ->setName(pht('View Live')) ->setDisabled(!$can_view_live) ->setWorkflow(!$can_view_live)); return $actions; } private function renderProperties( PhamePost $post, PhabricatorUser $user, PhabricatorActionListView $actions) { $properties = id(new PHUIPropertyListView()) ->setUser($user) ->setObject($post) ->setActionList($actions); $properties->addProperty( pht('Blog'), $post->getBlogPHID() ? $this->getHandle($post->getBlogPHID())->renderLink() : null); $properties->addProperty( pht('Blogger'), $this->getHandle($post->getBloggerPHID())->renderLink()); $properties->addProperty( pht('Published'), $post->isDraft() ? pht('Draft') : phabricator_datetime($post->getDatePublished(), $user)); $engine = id(new PhabricatorMarkupEngine()) ->setViewer($user) ->addObject($post, PhamePost::MARKUP_FIELD_BODY) ->process(); $properties->invokeWillRenderEvent(); $properties->addTextContent( phutil_tag( 'div', array( 'class' => 'phabricator-remarkup', ), $engine->getOutput($post, PhamePost::MARKUP_FIELD_BODY))); return $properties; } } diff --git a/src/applications/phragment/controller/PhragmentHistoryController.php b/src/applications/phragment/controller/PhragmentHistoryController.php index 3cd282e91a..396a2a38bf 100644 --- a/src/applications/phragment/controller/PhragmentHistoryController.php +++ b/src/applications/phragment/controller/PhragmentHistoryController.php @@ -1,111 +1,111 @@ dblob = idx($data, "dblob", ""); } public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); $parents = $this->loadParentFragments($this->dblob); if ($parents === null) { return new Aphront404Response(); } $current = idx($parents, count($parents) - 1, null); $path = $current->getPath(); $crumbs = $this->buildApplicationCrumbsWithPath($parents); if ($this->hasApplicationCapability( PhragmentCapabilityCanCreate::CAPABILITY)) { $crumbs->addAction( id(new PHUIListItemView()) ->setName(pht('Create Fragment')) ->setHref($this->getApplicationURI('/create/'.$path)) ->setIcon('fa-plus-square')); } $current_box = $this->createCurrentFragmentView($current, true); $versions = id(new PhragmentFragmentVersionQuery()) ->setViewer($viewer) ->withFragmentPHIDs(array($current->getPHID())) ->execute(); $list = id(new PHUIObjectItemListView()) ->setUser($viewer); $file_phids = mpull($versions, 'getFilePHID'); $files = id(new PhabricatorFileQuery()) ->setViewer($viewer) ->withPHIDs($file_phids) ->execute(); $files = mpull($files, null, 'getPHID'); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $current, PhabricatorPolicyCapability::CAN_EDIT); $first = true; foreach ($versions as $version) { $item = id(new PHUIObjectItemView()); $item->setHeader('Version '.$version->getSequence()); $item->setHref($version->getURI()); $item->addAttribute(phabricator_datetime( $version->getDateCreated(), $viewer)); if ($version->getFilePHID() === null) { $item->setDisabled(true); $item->addAttribute('Deletion'); } if (!$first && $can_edit) { $item->addAction(id(new PHUIListItemView()) - ->setIcon('undo') + ->setIcon('fa-refresh') ->setRenderNameAsTooltip(true) ->setWorkflow(true) ->setName(pht("Revert to Here")) ->setHref($this->getApplicationURI( "revert/".$version->getID()."/".$current->getPath()))); } $disabled = !isset($files[$version->getFilePHID()]); $action = id(new PHUIListItemView()) - ->setIcon('download') + ->setIcon('fa-download') ->setDisabled($disabled || !$this->isCorrectlyConfigured()) ->setRenderNameAsTooltip(true) ->setName(pht("Download")); if (!$disabled && $this->isCorrectlyConfigured()) { $action->setHref($files[$version->getFilePHID()] ->getDownloadURI($version->getURI())); } $item->addAction($action); $list->addItem($item); $first = false; } return $this->buildApplicationPage( array( $crumbs, $this->renderConfigurationWarningIfRequired(), $current_box, $list), array( 'title' => pht('Fragment History'), 'device' => true)); } } diff --git a/src/applications/phragment/controller/PhragmentSnapshotViewController.php b/src/applications/phragment/controller/PhragmentSnapshotViewController.php index 47663e6331..26d2a9f171 100644 --- a/src/applications/phragment/controller/PhragmentSnapshotViewController.php +++ b/src/applications/phragment/controller/PhragmentSnapshotViewController.php @@ -1,154 +1,154 @@ id = idx($data, "id", ""); } public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); $snapshot = id(new PhragmentSnapshotQuery()) ->setViewer($viewer) ->withIDs(array($this->id)) ->executeOne(); if ($snapshot === null) { return new Aphront404Response(); } $box = $this->createSnapshotView($snapshot); $fragment = id(new PhragmentFragmentQuery()) ->setViewer($viewer) ->withPHIDs(array($snapshot->getPrimaryFragmentPHID())) ->executeOne(); if ($fragment === null) { return new Aphront404Response(); } $parents = $this->loadParentFragments($fragment->getPath()); if ($parents === null) { return new Aphront404Response(); } $crumbs = $this->buildApplicationCrumbsWithPath($parents); $crumbs->addTextCrumb(pht('"%s" Snapshot', $snapshot->getName())); $children = id(new PhragmentSnapshotChildQuery()) ->setViewer($viewer) ->needFragments(true) ->needFragmentVersions(true) ->withSnapshotPHIDs(array($snapshot->getPHID())) ->execute(); $list = id(new PHUIObjectItemListView()) ->setUser($viewer); foreach ($children as $child) { $item = id(new PHUIObjectItemView()) ->setHeader($child->getFragment()->getPath()); if ($child->getFragmentVersion() !== null) { $item ->setHref($child->getFragmentVersion()->getURI()) ->addAttribute(pht( 'Version %s', $child->getFragmentVersion()->getSequence())); } else { $item ->setHref($child->getFragment()->getURI()) ->addAttribute(pht('Directory')); } $list->addItem($item); } return $this->buildApplicationPage( array( $crumbs, $this->renderConfigurationWarningIfRequired(), $box, $list), array( 'title' => pht('View Snapshot'), 'device' => true)); } protected function createSnapshotView($snapshot) { if ($snapshot === null) { return null; } $viewer = $this->getRequest()->getUser(); $phids = array(); $phids[] = $snapshot->getPrimaryFragmentPHID(); $this->loadHandles($phids); $header = id(new PHUIHeaderView()) ->setHeader(pht('"%s" Snapshot', $snapshot->getName())) ->setPolicyObject($snapshot) ->setUser($viewer); $zip_uri = $this->getApplicationURI( "zip@".$snapshot->getName(). "/".$snapshot->getPrimaryFragment()->getPath()); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $snapshot, PhabricatorPolicyCapability::CAN_EDIT); $actions = id(new PhabricatorActionListView()) ->setUser($viewer) ->setObject($snapshot) ->setObjectURI($snapshot->getURI()); $actions->addAction( id(new PhabricatorActionView()) ->setName(pht('Download Snapshot as ZIP')) ->setHref($this->isCorrectlyConfigured() ? $zip_uri : null) ->setDisabled(!$this->isCorrectlyConfigured()) - ->setIcon('zip')); + ->setIcon('fa-floppy-o')); $actions->addAction( id(new PhabricatorActionView()) ->setName(pht('Delete Snapshot')) ->setHref($this->getApplicationURI( "snapshot/delete/".$snapshot->getID()."/")) ->setDisabled(!$can_edit) ->setWorkflow(true) - ->setIcon('delete')); + ->setIcon('fa-times')); $actions->addAction( id(new PhabricatorActionView()) ->setName(pht('Promote Another Snapshot to Here')) ->setHref($this->getApplicationURI( "snapshot/promote/".$snapshot->getID()."/")) ->setDisabled(!$can_edit) ->setWorkflow(true) - ->setIcon('promote')); + ->setIcon('fa-arrow-up')); $properties = id(new PHUIPropertyListView()) ->setUser($viewer) ->setObject($snapshot) ->setActionList($actions); $properties->addProperty( pht('Name'), $snapshot->getName()); $properties->addProperty( pht('Fragment'), $this->renderHandlesForPHIDs(array($snapshot->getPrimaryFragmentPHID()))); return id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); } } diff --git a/src/applications/phragment/controller/PhragmentVersionController.php b/src/applications/phragment/controller/PhragmentVersionController.php index 803d0afb56..0373f55e83 100644 --- a/src/applications/phragment/controller/PhragmentVersionController.php +++ b/src/applications/phragment/controller/PhragmentVersionController.php @@ -1,136 +1,136 @@ id = idx($data, "id", 0); } public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); $version = id(new PhragmentFragmentVersionQuery()) ->setViewer($viewer) ->withIDs(array($this->id)) ->executeOne(); if ($version === null) { return new Aphront404Response(); } $parents = $this->loadParentFragments($version->getFragment()->getPath()); if ($parents === null) { return new Aphront404Response(); } $current = idx($parents, count($parents) - 1, null); $crumbs = $this->buildApplicationCrumbsWithPath($parents); $crumbs->addTextCrumb(pht('View Version %d', $version->getSequence())); $phids = array(); $phids[] = $version->getFilePHID(); $this->loadHandles($phids); $file = id(new PhabricatorFileQuery()) ->setViewer($viewer) ->withPHIDs(array($version->getFilePHID())) ->executeOne(); if ($file !== null) { $file_uri = $file->getDownloadURI(); } $header = id(new PHUIHeaderView()) ->setHeader(pht( "%s at version %d", $version->getFragment()->getName(), $version->getSequence())) ->setPolicyObject($version) ->setUser($viewer); $actions = id(new PhabricatorActionListView()) ->setUser($viewer) ->setObject($version) ->setObjectURI($version->getURI()); $actions->addAction( id(new PhabricatorActionView()) ->setName(pht('Download Version')) ->setDisabled($file === null || !$this->isCorrectlyConfigured()) ->setHref($this->isCorrectlyConfigured() ? $file_uri : null) - ->setIcon('download')); + ->setIcon('fa-download')); $properties = id(new PHUIPropertyListView()) ->setUser($viewer) ->setObject($version) ->setActionList($actions); $properties->addProperty( pht('File'), $this->renderHandlesForPHIDs(array($version->getFilePHID()))); $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); return $this->buildApplicationPage( array( $crumbs, $this->renderConfigurationWarningIfRequired(), $box, $this->renderPreviousVersionList($version)), array( 'title' => pht('View Version'), 'device' => true)); } private function renderPreviousVersionList( PhragmentFragmentVersion $version) { $request = $this->getRequest(); $viewer = $request->getUser(); $previous_versions = id(new PhragmentFragmentVersionQuery()) ->setViewer($viewer) ->withFragmentPHIDs(array($version->getFragmentPHID())) ->withSequenceBefore($version->getSequence()) ->execute(); $list = id(new PHUIObjectItemListView()) ->setUser($viewer); foreach ($previous_versions as $previous_version) { $item = id(new PHUIObjectItemView()); $item->setHeader('Version '.$previous_version->getSequence()); $item->setHref($previous_version->getURI()); $item->addAttribute(phabricator_datetime( $previous_version->getDateCreated(), $viewer)); $patch_uri = $this->getApplicationURI( 'patch/'.$previous_version->getID().'/'.$version->getID()); $item->addAction(id(new PHUIListItemView()) - ->setIcon('patch') + ->setIcon('fa-file-o') ->setName(pht("Get Patch")) ->setHref($this->isCorrectlyConfigured() ? $patch_uri : null) ->setDisabled(!$this->isCorrectlyConfigured())); $list->addItem($item); } $item = id(new PHUIObjectItemView()); $item->setHeader('Prior to Version 0'); $item->addAttribute('Prior to any content (empty file)'); $item->addAction(id(new PHUIListItemView()) - ->setIcon('patch') + ->setIcon('fa-file-o') ->setName(pht("Get Patch")) ->setHref($this->getApplicationURI( 'patch/x/'.$version->getID()))); $list->addItem($item); return $list; } } diff --git a/src/applications/phrequent/query/PhrequentSearchEngine.php b/src/applications/phrequent/query/PhrequentSearchEngine.php index cb1a4c77e0..abf92b8cbe 100644 --- a/src/applications/phrequent/query/PhrequentSearchEngine.php +++ b/src/applications/phrequent/query/PhrequentSearchEngine.php @@ -1,202 +1,202 @@ getParameter('limit', 1000); } public function buildSavedQueryFromRequest(AphrontRequest $request) { $saved = new PhabricatorSavedQuery(); $saved->setParameter( 'userPHIDs', $this->readUsersFromRequest($request, 'users')); $saved->setParameter('ended', $request->getStr('ended')); $saved->setParameter('order', $request->getStr('order')); return $saved; } public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { $query = id(new PhrequentUserTimeQuery()); $user_phids = $saved->getParameter('userPHIDs'); if ($user_phids) { $query->withUserPHIDs($user_phids); } $ended = $saved->getParameter('ended'); if ($ended != null) { $query->withEnded($ended); } $order = $saved->getParameter('order'); if ($order != null) { $query->setOrder($order); } return $query; } public function buildSearchForm( AphrontFormView $form, PhabricatorSavedQuery $saved_query) { $user_phids = $saved_query->getParameter('userPHIDs', array()); $ended = $saved_query->getParameter( 'ended', PhrequentUserTimeQuery::ENDED_ALL); $order = $saved_query->getParameter( 'order', PhrequentUserTimeQuery::ORDER_ENDED_DESC); $phids = array_merge($user_phids); $handles = id(new PhabricatorHandleQuery()) ->setViewer($this->requireViewer()) ->withPHIDs($phids) ->execute(); $form ->appendChild( id(new AphrontFormTokenizerControl()) ->setDatasource('/typeahead/common/users/') ->setName('users') ->setLabel(pht('Users')) ->setValue($handles)) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel(pht('Ended')) ->setName('ended') ->setValue($ended) ->setOptions(PhrequentUserTimeQuery::getEndedSearchOptions())) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel(pht('Order')) ->setName('order') ->setValue($order) ->setOptions(PhrequentUserTimeQuery::getOrderSearchOptions())); } protected function getURI($path) { return '/phrequent/'.$path; } public function getBuiltinQueryNames() { $names = array( 'tracking' => pht('Currently Tracking'), 'all' => pht('All Tracked'), ); return $names; } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); switch ($query_key) { case 'all': return $query ->setParameter('order', PhrequentUserTimeQuery::ORDER_ENDED_DESC); case 'tracking': return $query ->setParameter('ended', PhrequentUserTimeQuery::ENDED_NO) ->setParameter('order', PhrequentUserTimeQuery::ORDER_ENDED_DESC); } return parent::buildSavedQueryFromBuiltin($query_key); } protected function getRequiredHandlePHIDsForResultList( array $usertimes, PhabricatorSavedQuery $query) { return array_mergev( array( mpull($usertimes, 'getUserPHID'), mpull($usertimes, 'getObjectPHID'), )); } protected function renderResultList( array $usertimes, PhabricatorSavedQuery $query, array $handles) { assert_instances_of($usertimes, 'PhrequentUserTime'); $viewer = $this->requireViewer(); $view = id(new PHUIObjectItemListView()) ->setUser($viewer); foreach ($usertimes as $usertime) { $item = new PHUIObjectItemView(); if ($usertime->getObjectPHID() === null) { $item->setHeader($usertime->getNote()); } else { $obj = $handles[$usertime->getObjectPHID()]; $item->setHeader($obj->getLinkName()); $item->setHref($obj->getURI()); } $item->setObject($usertime); $item->addByline( pht( 'Tracked: %s', $handles[$usertime->getUserPHID()]->renderLink())); $started_date = phabricator_date($usertime->getDateStarted(), $viewer); $item->addIcon('none', $started_date); if ($usertime->getDateEnded() !== null) { $time_spent = $usertime->getDateEnded() - $usertime->getDateStarted(); $time_ended = phabricator_datetime($usertime->getDateEnded(), $viewer); } else { $time_spent = time() - $usertime->getDateStarted(); } $time_spent = $time_spent == 0 ? 'none' : phabricator_format_relative_time_detailed($time_spent); if ($usertime->getDateEnded() !== null) { $item->addAttribute( pht( 'Tracked %s', $time_spent)); $item->addAttribute( pht( 'Ended on %s', $time_ended)); } else { $item->addAttribute( pht( 'Tracked %s so far', $time_spent)); if ($usertime->getObjectPHID() !== null && $usertime->getUserPHID() === $viewer->getPHID()) { $item->addAction( id(new PHUIListItemView()) - ->setIcon('history') + ->setIcon('fa-time-o') ->addSigil('phrequent-stop-tracking') ->setWorkflow(true) ->setRenderNameAsTooltip(true) ->setName(pht("Stop")) ->setHref( '/phrequent/track/stop/'. $usertime->getObjectPHID().'/')); } $item->setBarColor('green'); } $view->addItem($item); } return $view; } } diff --git a/src/applications/settings/panel/PhabricatorSettingsPanelExternalAccounts.php b/src/applications/settings/panel/PhabricatorSettingsPanelExternalAccounts.php index 18030c35c7..284da8da70 100644 --- a/src/applications/settings/panel/PhabricatorSettingsPanelExternalAccounts.php +++ b/src/applications/settings/panel/PhabricatorSettingsPanelExternalAccounts.php @@ -1,147 +1,147 @@ getUser(); $providers = PhabricatorAuthProvider::getAllProviders(); $accounts = id(new PhabricatorExternalAccountQuery()) ->setViewer($viewer) ->withUserPHIDs(array($viewer->getPHID())) ->needImages(true) ->execute(); $linked_head = id(new PHUIHeaderView()) ->setHeader(pht('Linked Accounts and Authentication')); $linked = id(new PHUIObjectItemListView()) ->setUser($viewer) ->setCards(true) ->setFlush(true) ->setNoDataString(pht('You have no linked accounts.')); $login_accounts = 0; foreach ($accounts as $account) { if ($account->isUsableForLogin()) { $login_accounts++; } } foreach ($accounts as $account) { $item = id(new PHUIObjectItemView()); $provider = idx($providers, $account->getProviderKey()); if ($provider) { $item->setHeader($provider->getProviderName()); $can_unlink = $provider->shouldAllowAccountUnlink(); if (!$can_unlink) { $item->addAttribute(pht('Permanently Linked')); } } else { $item->setHeader( pht('Unknown Account ("%s")', $account->getProviderKey())); $can_unlink = true; } $can_login = $account->isUsableForLogin(); if (!$can_login) { $item->addAttribute( pht( 'Disabled (an administrator has disabled login for this '. 'account provider).')); } $can_unlink = $can_unlink && (!$can_login || ($login_accounts > 1)); $can_refresh = $provider && $provider->shouldAllowAccountRefresh(); if ($can_refresh) { $item->addAction( id(new PHUIListItemView()) - ->setIcon('refresh') + ->setIcon('fa-refresh') ->setHref('/auth/refresh/'.$account->getProviderKey().'/')); } $item->addAction( id(new PHUIListItemView()) - ->setIcon('delete') + ->setIcon('fa-times') ->setWorkflow(true) ->setDisabled(!$can_unlink) ->setHref('/auth/unlink/'.$account->getProviderKey().'/')); if ($provider) { $provider->willRenderLinkedAccount($viewer, $item, $account); } $linked->addItem($item); } $linkable_head = id(new PHUIHeaderView()) ->setHeader(pht('Add External Account')); $linkable = id(new PHUIObjectItemListView()) ->setUser($viewer) ->setCards(true) ->setFlush(true) ->setNoDataString( pht('Your account is linked with all available providers.')); $accounts = mpull($accounts, null, 'getProviderKey'); $providers = PhabricatorAuthProvider::getAllEnabledProviders(); $providers = msort($providers, 'getProviderName'); foreach ($providers as $key => $provider) { if (isset($accounts[$key])) { continue; } if (!$provider->shouldAllowAccountLink()) { continue; } $link_uri = '/auth/link/'.$provider->getProviderKey().'/'; $item = id(new PHUIObjectItemView()); $item->setHeader($provider->getProviderName()); $item->setHref($link_uri); $item->addAction( id(new PHUIListItemView()) - ->setIcon('link') + ->setIcon('fa-link') ->setHref($link_uri)); $linkable->addItem($item); } $linked_box = id(new PHUIObjectBoxView()) ->setHeader($linked_head) ->appendChild($linked); $linkable_box = id(new PHUIObjectBoxView()) ->setHeader($linkable_head) ->appendChild($linkable); return array( $linked_box, $linkable_box, ); } } diff --git a/src/applications/uiexample/examples/PHUITimelineExample.php b/src/applications/uiexample/examples/PHUITimelineExample.php index 75c04ff398..cfd5837c62 100644 --- a/src/applications/uiexample/examples/PHUITimelineExample.php +++ b/src/applications/uiexample/examples/PHUITimelineExample.php @@ -1,200 +1,200 @@ PHUITimelineView to comments and transactions.'); } public function renderExample() { $request = $this->getRequest(); $user = $request->getUser(); $handle = id(new PhabricatorHandleQuery()) ->setViewer($user) ->withPHIDs(array($user->getPHID())) ->executeOne(); $events = array(); $events[] = id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setTitle('A major event.') ->appendChild('This is a major timeline event.'); $events[] = id(new PHUITimelineEventView()) ->setUserHandle($handle) - ->setIcon('love') + ->setIcon('fa-heart') ->setTitle('A minor event.'); $events[] = id(new PHUITimelineEventView()) ->setUserHandle($handle) - ->setIcon('comment') + ->setIcon('fa-comment') ->appendChild('A major event with no title.'); $events[] = id(new PHUITimelineEventView()) ->setUserHandle($handle) - ->setIcon('dislike') + ->setIcon('fa-star') ->setTitle('Another minor event.'); $events[] = id(new PHUITimelineEventView()) - ->setIcon('like') + ->setIcon('fa-trophy') ->setToken('medal-1') ->setUserHandle($handle); $events[] = id(new PHUITimelineEventView()) - ->setIcon('dislike') + ->setIcon('fa-quote-left') ->setToken('medal-1', true) ->setUserHandle($handle); $events[] = id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setTitle('Major Red Event') - ->setIcon('love') + ->setIcon('fa-heart-o') ->appendChild('This event is red!') ->setColor(PhabricatorTransactions::COLOR_RED); $events[] = id(new PHUITimelineEventView()) ->setUserHandle($handle) - ->setIcon('love') + ->setIcon('fa-female') ->setTitle('Minor Red Event') ->setColor(PhabricatorTransactions::COLOR_RED); $events[] = id(new PHUITimelineEventView()) - ->setIcon('like') + ->setIcon('fa-refresh') ->setUserHandle($handle) ->setTitle('Minor Not-Red Event') ->setColor(PhabricatorTransactions::COLOR_GREEN); $events[] = id(new PHUITimelineEventView()) ->setUserHandle($handle) - ->setIcon('love') + ->setIcon('fa-calendar-o') ->setTitle('Minor Red Event') ->setColor(PhabricatorTransactions::COLOR_RED); $events[] = id(new PHUITimelineEventView()) ->setUserHandle($handle) - ->setIcon('dislike') + ->setIcon('fa-random') ->setTitle('Minor Not-Red Event') ->setColor(PhabricatorTransactions::COLOR_BLACK); $events[] = id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setIcon('tag') ->setTitle('Major Green Event') ->appendChild('This event is green!') ->setColor(PhabricatorTransactions::COLOR_GREEN); $events[] = id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setIcon('tag') ->setTitle(str_repeat('Long Text Title ', 64)) ->appendChild(str_repeat('Long Text Body ', 64)) ->setColor(PhabricatorTransactions::COLOR_ORANGE); $events[] = id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setTitle(str_repeat('LongTextEventNoSpaces', 1024)) ->appendChild(str_repeat('LongTextNoSpaces', 1024)) ->setColor(PhabricatorTransactions::COLOR_RED); $colors = array( PhabricatorTransactions::COLOR_RED, PhabricatorTransactions::COLOR_ORANGE, PhabricatorTransactions::COLOR_YELLOW, PhabricatorTransactions::COLOR_GREEN, PhabricatorTransactions::COLOR_SKY, PhabricatorTransactions::COLOR_BLUE, PhabricatorTransactions::COLOR_INDIGO, PhabricatorTransactions::COLOR_VIOLET, PhabricatorTransactions::COLOR_GREY, PhabricatorTransactions::COLOR_BLACK, ); $events[] = id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setTitle("Colorless") ->setIcon('lock'); foreach ($colors as $color) { $events[] = id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setTitle("Color '{$color}'") ->setIcon('lock') ->setColor($color); } $vhandle = $handle->renderLink(); $group_event = id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setTitle(pht('%s went to the store.', $vhandle)); $group_event->addEventToGroup( id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setTitle(pht('%s bought an apple.', $vhandle)) ->setColor('green') ->setIcon('check')); $group_event->addEventToGroup( id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setTitle(pht('%s bought a banana.', $vhandle)) ->setColor('yellow') ->setIcon('check')); $group_event->addEventToGroup( id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setTitle(pht('%s bought a cherry.', $vhandle)) ->setColor('red') ->setIcon('check')); $group_event->addEventToGroup( id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setTitle(pht('%s paid for his goods.', $vhandle))); $group_event->addEventToGroup( id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setTitle(pht('%s returned home.', $vhandle)) ->setIcon('home') ->setColor('blue')); $group_event->addEventToGroup( id(new PHUITimelineEventView()) ->setUserHandle($handle) ->setTitle(pht('%s related on his adventures.', $vhandle)) ->appendChild( pht( 'Today, I went to the store. I bought an apple. I bought a '. 'banana. I bought a cherry. I paid for my goods, then I returned '. 'home.'))); $events[] = $group_event; $anchor = 0; foreach ($events as $group) { foreach ($group->getEventGroup() as $event) { $event->setUser($user); $event->setDateCreated(time() + ($anchor * 60 * 8)); $event->setAnchor(++$anchor); } } $timeline = id(new PHUITimelineView()); foreach ($events as $event) { $timeline->addEvent($event); } return $timeline; } } diff --git a/src/infrastructure/customfield/config/PhabricatorCustomFieldConfigOptionType.php b/src/infrastructure/customfield/config/PhabricatorCustomFieldConfigOptionType.php index ef6417ac5f..b26441f233 100644 --- a/src/infrastructure/customfield/config/PhabricatorCustomFieldConfigOptionType.php +++ b/src/infrastructure/customfield/config/PhabricatorCustomFieldConfigOptionType.php @@ -1,137 +1,137 @@ getStr('value'); $in_value = json_decode($storage_value, true); if (!is_array($in_value)) { $in_value = array(); } // When we submit from JS, we submit a list (since maps are not guaranteed // to retain order). Convert it into a map for storage (since it's far more // convenient for us elsewhere). $storage_value = ipull($in_value, null, 'key'); $display_value = $storage_value; return array($e_value, $errors, $storage_value, $display_value); } public function renderControl( PhabricatorConfigOption $option, $display_value, $e_value) { $field_base_class = $option->getCustomData(); $field_spec = $display_value; if (!is_array($field_spec)) { $field_spec = PhabricatorEnv::getEnvConfig($option->getKey()); } // Get all of the fields (including disabled fields) by querying for them // with a faux spec where no fields are disabled. $faux_spec = $field_spec; foreach ($faux_spec as $key => $spec) { unset($faux_spec[$key]['disabled']); } // TODO: We might need to build a real object here eventually. $faux_object = null; $fields = PhabricatorCustomField::buildFieldList( $field_base_class, $faux_spec, $faux_object); $list_id = celerity_generate_unique_node_id(); $input_id = celerity_generate_unique_node_id(); $list = id(new PHUIObjectItemListView()) ->setFlush(true) ->setID($list_id); foreach ($fields as $key => $field) { $item = id(new PHUIObjectItemView()) ->addSigil('field-spec') ->setMetadata(array('fieldKey' => $key)) ->setGrippable(true) ->addAttribute($field->getFieldDescription()) ->setHeader($field->getFieldName()); $is_disabled = !empty($field_spec[$key]['disabled']); $disabled_item = clone $item; $enabled_item = clone $item; if ($is_disabled) { $list->addItem($disabled_item); } else { $list->addItem($enabled_item); } $disabled_item->addIcon('none', pht('Disabled')); $disabled_item->setDisabled(true); $disabled_item->addAction( id(new PHUIListItemView()) ->setHref('#') ->addSigil('field-spec-toggle') - ->setIcon('new')); + ->setIcon('fa-plus')); $enabled_item->setBarColor('green'); if (!$field->canDisableField()) { $enabled_item->addAction( id(new PHUIListItemView()) - ->setIcon('lock-grey')); + ->setIcon('fa-lock grey')); $enabled_item->addIcon('none', pht('Permanent Field')); } else { $enabled_item->addAction( id(new PHUIListItemView()) ->setHref('#') ->addSigil('field-spec-toggle') - ->setIcon('delete')); + ->setIcon('fa-times')); } $fields[$key] = array( 'disabled' => $is_disabled, 'disabledMarkup' => $disabled_item->render(), 'enabledMarkup' => $enabled_item->render(), ); } $input = phutil_tag( 'input', array( 'id' => $input_id, 'type' => 'hidden', 'name' => 'value', 'value' => json_encode($display_value), )); Javelin::initBehavior( 'config-reorder-fields', array( 'listID' => $list_id, 'inputID' => $input_id, 'fields' => $fields, )); return id(new AphrontFormMarkupControl()) ->setLabel(pht('Value')) ->setError($e_value) ->setValue( array( $list, $input, )); } }