diff --git a/src/applications/badges/controller/PhabricatorBadgesViewController.php b/src/applications/badges/controller/PhabricatorBadgesViewController.php index 3858965d41..fac82ccc8d 100644 --- a/src/applications/badges/controller/PhabricatorBadgesViewController.php +++ b/src/applications/badges/controller/PhabricatorBadgesViewController.php @@ -1,209 +1,193 @@ getViewer(); $id = $request->getURIData('id'); $badge = id(new PhabricatorBadgesQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needRecipients(true) ->executeOne(); if (!$badge) { return new Aphront404Response(); } $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($badge->getName()); $crumbs->setBorder(true); $title = $badge->getName(); if ($badge->isArchived()) { $status_icon = 'fa-ban'; $status_color = 'dark'; } else { $status_icon = 'fa-check'; $status_color = 'bluegrey'; } $status_name = idx( PhabricatorBadgesBadge::getStatusNameMap(), $badge->getStatus()); $header = id(new PHUIHeaderView()) ->setHeader($badge->getName()) ->setUser($viewer) ->setPolicyObject($badge) ->setStatus($status_icon, $status_color, $status_name) ->setHeaderIcon('fa-trophy'); - $properties = $this->buildPropertyListView($badge); - $actions = $this->buildActionListView($badge); + $curtain = $this->buildCurtain($badge); $details = $this->buildDetailsView($badge); $timeline = $this->buildTransactionTimeline( $badge, new PhabricatorBadgesTransactionQuery()); $recipient_phids = $badge->getRecipientPHIDs(); $recipient_phids = array_reverse($recipient_phids); $handles = $this->loadViewerHandles($recipient_phids); $recipient_list = id(new PhabricatorBadgesRecipientsListView()) ->setBadge($badge) ->setHandles($handles) ->setUser($viewer); $add_comment = $this->buildCommentForm($badge); $view = id(new PHUITwoColumnView()) ->setHeader($header) + ->setCurtain($curtain) ->setMainColumn(array( $recipient_list, $timeline, $add_comment, )) - ->setPropertyList($properties) - ->setActionList($actions) ->addPropertySection(pht('BADGE DETAILS'), $details); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->setPageObjectPHIDs(array($badge->getPHID())) - ->appendChild( - array( - $view, - )); - } - - private function buildPropertyListView( - PhabricatorBadgesBadge $badge) { - $viewer = $this->getViewer(); - - $view = id(new PHUIPropertyListView()) - ->setUser($viewer) - ->setObject($badge); - - $view->invokeWillRenderEvent(); - - return $view; + ->appendChild($view); } private function buildDetailsView( PhabricatorBadgesBadge $badge) { $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView()) ->setUser($viewer); $quality = idx($badge->getQualityNameMap(), $badge->getQuality()); $view->addProperty( pht('Quality'), $quality); $view->addProperty( pht('Icon'), id(new PhabricatorBadgesIconSet()) ->getIconLabel($badge->getIcon())); $view->addProperty( pht('Flavor'), $badge->getFlavor()); $description = $badge->getDescription(); if (strlen($description)) { $view->addSectionHeader( pht('Description'), PHUIPropertyListView::ICON_SUMMARY); $view->addTextContent( new PHUIRemarkupView($viewer, $description)); } $badge = id(new PHUIBadgeView()) ->setIcon($badge->getIcon()) ->setHeader($badge->getName()) ->setSubhead($badge->getFlavor()) ->setQuality($badge->getQuality()); $view->addTextContent($badge); return $view; } - private function buildActionListView(PhabricatorBadgesBadge $badge) { + private function buildCurtain(PhabricatorBadgesBadge $badge) { $viewer = $this->getViewer(); - $id = $badge->getID(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $badge, PhabricatorPolicyCapability::CAN_EDIT); - $view = id(new PhabricatorActionListView()) - ->setUser($viewer) - ->setObject($badge); + $id = $badge->getID(); + $edit_uri = $this->getApplicationURI("/edit/{$id}/"); + $archive_uri = $this->getApplicationURI("/archive/{$id}/"); + $award_uri = $this->getApplicationURI("/recipients/{$id}/"); + + $curtain = $this->newCurtainView($badge); - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Badge')) ->setIcon('fa-pencil') ->setDisabled(!$can_edit) - ->setHref($this->getApplicationURI("/edit/{$id}/"))); + ->setHref($edit_uri)); if ($badge->isArchived()) { - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Activate Badge')) ->setIcon('fa-check') ->setDisabled(!$can_edit) ->setWorkflow($can_edit) - ->setHref($this->getApplicationURI("/archive/{$id}/"))); + ->setHref($archive_uri)); } else { - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Archive Badge')) ->setIcon('fa-ban') ->setDisabled(!$can_edit) ->setWorkflow($can_edit) - ->setHref($this->getApplicationURI("/archive/{$id}/"))); + ->setHref($archive_uri)); } - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName('Add Recipients') ->setIcon('fa-users') ->setDisabled(!$can_edit) ->setWorkflow(true) - ->setHref($this->getApplicationURI("/recipients/{$id}/"))); + ->setHref($award_uri)); - return $view; + return $curtain; } private function buildCommentForm(PhabricatorBadgesBadge $badge) { $viewer = $this->getViewer(); $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); $add_comment_header = $is_serious ? pht('Add Comment') : pht('Render Honors'); $draft = PhabricatorDraft::newFromUserAndKey($viewer, $badge->getPHID()); return id(new PhabricatorApplicationTransactionCommentView()) ->setUser($viewer) ->setObjectPHID($badge->getPHID()) ->setDraft($draft) ->setHeaderText($add_comment_header) ->setAction($this->getApplicationURI('/comment/'.$badge->getID().'/')) ->setSubmitButtonName(pht('Add Comment')); } } diff --git a/src/applications/base/controller/PhabricatorController.php b/src/applications/base/controller/PhabricatorController.php index fffe299b3f..5d8ff7ba60 100644 --- a/src/applications/base/controller/PhabricatorController.php +++ b/src/applications/base/controller/PhabricatorController.php @@ -1,609 +1,615 @@ shouldRequireLogin()) { return false; } if (!$this->shouldRequireEnabledUser()) { return false; } if ($this->shouldAllowPartialSessions()) { return false; } $user = $this->getRequest()->getUser(); if (!$user->getIsStandardUser()) { return false; } return PhabricatorEnv::getEnvConfig('security.require-multi-factor-auth'); } public function shouldAllowLegallyNonCompliantUsers() { return false; } public function isGlobalDragAndDropUploadEnabled() { return false; } public function willBeginExecution() { $request = $this->getRequest(); if ($request->getUser()) { // NOTE: Unit tests can set a user explicitly. Normal requests are not // permitted to do this. PhabricatorTestCase::assertExecutingUnitTests(); $user = $request->getUser(); } else { $user = new PhabricatorUser(); $session_engine = new PhabricatorAuthSessionEngine(); $phsid = $request->getCookie(PhabricatorCookies::COOKIE_SESSION); if (strlen($phsid)) { $session_user = $session_engine->loadUserForSession( PhabricatorAuthSession::TYPE_WEB, $phsid); if ($session_user) { $user = $session_user; } } else { // If the client doesn't have a session token, generate an anonymous // session. This is used to provide CSRF protection to logged-out users. $phsid = $session_engine->establishSession( PhabricatorAuthSession::TYPE_WEB, null, $partial = false); // This may be a resource request, in which case we just don't set // the cookie. if ($request->canSetCookies()) { $request->setCookie(PhabricatorCookies::COOKIE_SESSION, $phsid); } } if (!$user->isLoggedIn()) { $user->attachAlternateCSRFString(PhabricatorHash::digest($phsid)); } $request->setUser($user); } PhabricatorEnv::setLocaleCode($user->getTranslation()); $preferences = $user->loadPreferences(); if (PhabricatorEnv::getEnvConfig('darkconsole.enabled')) { $dark_console = PhabricatorUserPreferences::PREFERENCE_DARK_CONSOLE; if ($preferences->getPreference($dark_console) || PhabricatorEnv::getEnvConfig('darkconsole.always-on')) { $console = new DarkConsoleCore(); $request->getApplicationConfiguration()->setConsole($console); } } // NOTE: We want to set up the user first so we can render a real page // here, but fire this before any real logic. $restricted = array( 'code', ); foreach ($restricted as $parameter) { if ($request->getExists($parameter)) { if (!$this->shouldAllowRestrictedParameter($parameter)) { throw new Exception( pht( 'Request includes restricted parameter "%s", but this '. 'controller ("%s") does not whitelist it. Refusing to '. 'serve this request because it might be part of a redirection '. 'attack.', $parameter, get_class($this))); } } } if ($this->shouldRequireEnabledUser()) { if ($user->isLoggedIn() && !$user->getIsApproved()) { $controller = new PhabricatorAuthNeedsApprovalController(); return $this->delegateToController($controller); } if ($user->getIsDisabled()) { $controller = new PhabricatorDisabledUserController(); return $this->delegateToController($controller); } } $auth_class = 'PhabricatorAuthApplication'; $auth_application = PhabricatorApplication::getByClass($auth_class); // Require partial sessions to finish login before doing anything. if (!$this->shouldAllowPartialSessions()) { if ($user->hasSession() && $user->getSession()->getIsPartial()) { $login_controller = new PhabricatorAuthFinishController(); $this->setCurrentApplication($auth_application); return $this->delegateToController($login_controller); } } // Check if the user needs to configure MFA. $need_mfa = $this->shouldRequireMultiFactorEnrollment(); $have_mfa = $user->getIsEnrolledInMultiFactor(); if ($need_mfa && !$have_mfa) { // Check if the cache is just out of date. Otherwise, roadblock the user // and require MFA enrollment. $user->updateMultiFactorEnrollment(); if (!$user->getIsEnrolledInMultiFactor()) { $mfa_controller = new PhabricatorAuthNeedsMultiFactorController(); $this->setCurrentApplication($auth_application); return $this->delegateToController($mfa_controller); } } if ($this->shouldRequireLogin()) { // This actually means we need either: // - a valid user, or a public controller; and // - permission to see the application; and // - permission to see at least one Space if spaces are configured. $allow_public = $this->shouldAllowPublic() && PhabricatorEnv::getEnvConfig('policy.allow-public'); // If this controller isn't public, and the user isn't logged in, require // login. if (!$allow_public && !$user->isLoggedIn()) { $login_controller = new PhabricatorAuthStartController(); $this->setCurrentApplication($auth_application); return $this->delegateToController($login_controller); } if ($user->isLoggedIn()) { if ($this->shouldRequireEmailVerification()) { if (!$user->getIsEmailVerified()) { $controller = new PhabricatorMustVerifyEmailController(); $this->setCurrentApplication($auth_application); return $this->delegateToController($controller); } } } // If Spaces are configured, require that the user have access to at // least one. If we don't do this, they'll get confusing error messages // later on. $spaces = PhabricatorSpacesNamespaceQuery::getSpacesExist(); if ($spaces) { $viewer_spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces( $user); if (!$viewer_spaces) { $controller = new PhabricatorSpacesNoAccessController(); return $this->delegateToController($controller); } } // If the user doesn't have access to the application, don't let them use // any of its controllers. We query the application in order to generate // a policy exception if the viewer doesn't have permission. $application = $this->getCurrentApplication(); if ($application) { id(new PhabricatorApplicationQuery()) ->setViewer($user) ->withPHIDs(array($application->getPHID())) ->executeOne(); } } if (!$this->shouldAllowLegallyNonCompliantUsers()) { $legalpad_class = 'PhabricatorLegalpadApplication'; $legalpad = id(new PhabricatorApplicationQuery()) ->setViewer($user) ->withClasses(array($legalpad_class)) ->withInstalled(true) ->execute(); $legalpad = head($legalpad); $doc_query = id(new LegalpadDocumentQuery()) ->setViewer($user) ->withSignatureRequired(1) ->needViewerSignatures(true); if ($user->hasSession() && !$user->getSession()->getIsPartial() && !$user->getSession()->getSignedLegalpadDocuments() && $user->isLoggedIn() && $legalpad) { $sign_docs = $doc_query->execute(); $must_sign_docs = array(); foreach ($sign_docs as $sign_doc) { if (!$sign_doc->getUserSignature($user->getPHID())) { $must_sign_docs[] = $sign_doc; } } if ($must_sign_docs) { $controller = new LegalpadDocumentSignController(); $this->getRequest()->setURIMap(array( 'id' => head($must_sign_docs)->getID(), )); $this->setCurrentApplication($legalpad); return $this->delegateToController($controller); } else { $engine = id(new PhabricatorAuthSessionEngine()) ->signLegalpadDocuments($user, $sign_docs); } } } // NOTE: We do this last so that users get a login page instead of a 403 // if they need to login. if ($this->shouldRequireAdmin() && !$user->getIsAdmin()) { return new Aphront403Response(); } } public function getApplicationURI($path = '') { if (!$this->getCurrentApplication()) { throw new Exception(pht('No application!')); } return $this->getCurrentApplication()->getApplicationURI($path); } public function willSendResponse(AphrontResponse $response) { $request = $this->getRequest(); if ($response instanceof AphrontDialogResponse) { if (!$request->isAjax() && !$request->isQuicksand()) { $dialog = $response->getDialog(); $title = $dialog->getTitle(); $short = $dialog->getShortTitle(); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(coalesce($short, $title)); $page_content = array( $crumbs, $response->buildResponseString(), ); $view = id(new PhabricatorStandardPageView()) ->setRequest($request) ->setController($this) ->setDeviceReady(true) ->setTitle($title) ->appendChild($page_content); $response = id(new AphrontWebpageResponse()) ->setContent($view->render()) ->setHTTPResponseCode($response->getHTTPResponseCode()); } else { $response->getDialog()->setIsStandalone(true); return id(new AphrontAjaxResponse()) ->setContent(array( 'dialog' => $response->buildResponseString(), )); } } else if ($response instanceof AphrontRedirectResponse) { if ($request->isAjax() || $request->isQuicksand()) { return id(new AphrontAjaxResponse()) ->setContent( array( 'redirect' => $response->getURI(), )); } } return $response; } /** * WARNING: Do not call this in new code. * * @deprecated See "Handles Technical Documentation". */ protected function loadViewerHandles(array $phids) { return id(new PhabricatorHandleQuery()) ->setViewer($this->getRequest()->getUser()) ->withPHIDs($phids) ->execute(); } public function buildApplicationMenu() { return null; } protected function buildApplicationCrumbs() { $crumbs = array(); $application = $this->getCurrentApplication(); if ($application) { $icon = $application->getIcon(); if (!$icon) { $icon = 'fa-puzzle'; } $crumbs[] = id(new PHUICrumbView()) ->setHref($this->getApplicationURI()) ->setName($application->getName()) ->setIcon($icon); } $view = new PHUICrumbsView(); foreach ($crumbs as $crumb) { $view->addCrumb($crumb); } return $view; } protected function hasApplicationCapability($capability) { return PhabricatorPolicyFilter::hasCapability( $this->getRequest()->getUser(), $this->getCurrentApplication(), $capability); } protected function requireApplicationCapability($capability) { PhabricatorPolicyFilter::requireCapability( $this->getRequest()->getUser(), $this->getCurrentApplication(), $capability); } protected function explainApplicationCapability( $capability, $positive_message, $negative_message) { $can_act = $this->hasApplicationCapability($capability); if ($can_act) { $message = $positive_message; $icon_name = 'fa-play-circle-o lightgreytext'; } else { $message = $negative_message; $icon_name = 'fa-lock'; } $icon = id(new PHUIIconView()) ->setIcon($icon_name); require_celerity_resource('policy-css'); $phid = $this->getCurrentApplication()->getPHID(); $explain_uri = "/policy/explain/{$phid}/{$capability}/"; $message = phutil_tag( 'div', array( 'class' => 'policy-capability-explanation', ), array( $icon, javelin_tag( 'a', array( 'href' => $explain_uri, 'sigil' => 'workflow', ), $message), )); return array($can_act, $message); } public function getDefaultResourceSource() { return 'phabricator'; } /** * Create a new @{class:AphrontDialogView} with defaults filled in. * * @return AphrontDialogView New dialog. */ public function newDialog() { $submit_uri = new PhutilURI($this->getRequest()->getRequestURI()); $submit_uri = $submit_uri->getPath(); return id(new AphrontDialogView()) ->setUser($this->getRequest()->getUser()) ->setSubmitURI($submit_uri); } public function newPage() { $page = id(new PhabricatorStandardPageView()) ->setRequest($this->getRequest()) ->setController($this) ->setDeviceReady(true); $application = $this->getCurrentApplication(); if ($application) { $page->setApplicationName($application->getName()); if ($application->getTitleGlyph()) { $page->setGlyph($application->getTitleGlyph()); } } $viewer = $this->getRequest()->getUser(); if ($viewer) { $page->setUser($viewer); } return $page; } public function newApplicationMenu() { return id(new PHUIApplicationMenuView()) ->setViewer($this->getViewer()); } public function newCurtainView($object) { $viewer = $this->getViewer(); $action_list = id(new PhabricatorActionListView()) - ->setViewer($viewer) - ->setObject($object); + ->setViewer($viewer); + + // NOTE: Applications (objects of class PhabricatorApplication) can't + // currently be set here, although they don't need any of the extensions + // anyway. This should probably work differently than it does, though. + if ($object instanceof PhabricatorLiskDAO) { + $action_list->setObject($object); + } $curtain = id(new PHUICurtainView()) ->setViewer($viewer) ->setActionList($action_list); $panels = PHUICurtainExtension::buildExtensionPanels($viewer, $object); foreach ($panels as $panel) { $curtain->addPanel($panel); } return $curtain; } protected function buildTransactionTimeline( PhabricatorApplicationTransactionInterface $object, PhabricatorApplicationTransactionQuery $query, PhabricatorMarkupEngine $engine = null, $render_data = array()) { $viewer = $this->getRequest()->getUser(); $xaction = $object->getApplicationTransactionTemplate(); $view = $xaction->getApplicationTransactionViewObject(); $pager = id(new AphrontCursorPagerView()) ->readFromRequest($this->getRequest()) ->setURI(new PhutilURI( '/transactions/showolder/'.$object->getPHID().'/')); $xactions = $query ->setViewer($viewer) ->withObjectPHIDs(array($object->getPHID())) ->needComments(true) ->executeWithCursorPager($pager); $xactions = array_reverse($xactions); if ($engine) { foreach ($xactions as $xaction) { if ($xaction->getComment()) { $engine->addObject( $xaction->getComment(), PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT); } } $engine->process(); $view->setMarkupEngine($engine); } $timeline = $view ->setUser($viewer) ->setObjectPHID($object->getPHID()) ->setTransactions($xactions) ->setPager($pager) ->setRenderData($render_data) ->setQuoteTargetID($this->getRequest()->getStr('quoteTargetID')) ->setQuoteRef($this->getRequest()->getStr('quoteRef')); $object->willRenderTimeline($timeline, $this->getRequest()); return $timeline; } public function buildApplicationCrumbsForEditEngine() { // TODO: This is kind of gross, I'm bascially just making this public so // I can use it in EditEngine. We could do this without making it public // by using controller delegation, or make it properly public. return $this->buildApplicationCrumbs(); } /* -( Deprecated )--------------------------------------------------------- */ /** * DEPRECATED. Use @{method:newPage}. */ public function buildStandardPageView() { return $this->newPage(); } /** * DEPRECATED. Use @{method:newPage}. */ public function buildStandardPageResponse($view, array $data) { $page = $this->buildStandardPageView(); $page->appendChild($view); return $page->produceAphrontResponse(); } /** * DEPRECATED. Use @{method:newPage}. */ public function buildApplicationPage($view, array $options) { $page = $this->newPage(); $title = PhabricatorEnv::getEnvConfig('phabricator.serious-business') ? 'Phabricator' : pht('Bacon Ice Cream for Breakfast'); $page->setTitle(idx($options, 'title', $title)); if (idx($options, 'class')) { $page->addClass($options['class']); } if (!($view instanceof AphrontSideNavFilterView)) { $nav = new AphrontSideNavFilterView(); $nav->appendChild($view); $view = $nav; } $page->appendChild($view); $object_phids = idx($options, 'pageObjects', array()); if ($object_phids) { $page->setPageObjectPHIDs($object_phids); } if (!idx($options, 'device', true)) { $page->setDeviceReady(false); } $page->setShowFooter(idx($options, 'showFooter', true)); $page->setShowChrome(idx($options, 'chrome', true)); return $page->produceAphrontResponse(); } } diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php b/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php index 8d13f85e61..eb435a42e9 100644 --- a/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php +++ b/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php @@ -1,402 +1,385 @@ getViewer(); $id = $request->getURIData('id'); $sequence = $request->getURIData('sequence'); $timeline = null; $event = id(new PhabricatorCalendarEventQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$event) { return new Aphront404Response(); } if ($sequence) { $result = $this->getEventAtIndexForGhostPHID( $viewer, $event->getPHID(), $sequence); if ($result) { $parent_event = $event; $event = $result; $event->attachParentEvent($parent_event); return id(new AphrontRedirectResponse()) ->setURI('/E'.$result->getID()); } else if ($sequence && $event->getIsRecurring()) { $parent_event = $event; $event = $event->generateNthGhost($sequence, $viewer); $event->attachParentEvent($parent_event); } else if ($sequence) { return new Aphront404Response(); } $title = $event->getMonogram().' ('.$sequence.')'; $page_title = $title.' '.$event->getName(); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($title, '/'.$event->getMonogram().'/'.$sequence); } else { $title = 'E'.$event->getID(); $page_title = $title.' '.$event->getName(); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($title); $crumbs->setBorder(true); } if (!$event->getIsGhostEvent()) { $timeline = $this->buildTransactionTimeline( $event, new PhabricatorCalendarEventTransactionQuery()); } $header = $this->buildHeaderView($event); - $actions = $this->buildActionView($event); - $properties = $this->buildPropertyListView($event); + $curtain = $this->buildCurtain($event); $details = $this->buildPropertySection($event); $description = $this->buildDescriptionView($event); $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); $add_comment_header = $is_serious ? pht('Add Comment') : pht('Add To Plate'); $draft = PhabricatorDraft::newFromUserAndKey($viewer, $event->getPHID()); if ($sequence) { $comment_uri = $this->getApplicationURI( '/event/comment/'.$event->getID().'/'.$sequence.'/'); } else { $comment_uri = $this->getApplicationURI( '/event/comment/'.$event->getID().'/'); } $add_comment_form = id(new PhabricatorApplicationTransactionCommentView()) ->setUser($viewer) ->setObjectPHID($event->getPHID()) ->setDraft($draft) ->setHeaderText($add_comment_header) ->setAction($comment_uri) ->setSubmitButtonName(pht('Add Comment')); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setMainColumn($timeline) - ->setPropertyList($properties) + ->setCurtain($curtain) ->addPropertySection(pht('DETAILS'), $details) - ->addPropertySection(pht('DESCRIPTION'), $description) - ->setActionList($actions); + ->addPropertySection(pht('DESCRIPTION'), $description); return $this->newPage() ->setTitle($page_title) ->setCrumbs($crumbs) ->setPageObjectPHIDs(array($event->getPHID())) ->appendChild( array( $view, )); } private function buildHeaderView( PhabricatorCalendarEvent $event) { $viewer = $this->getViewer(); $id = $event->getID(); $is_cancelled = $event->getIsCancelled(); $icon = $is_cancelled ? ('fa-ban') : ('fa-check'); $color = $is_cancelled ? ('red') : ('bluegrey'); $status = $is_cancelled ? pht('Cancelled') : pht('Active'); $invite_status = $event->getUserInviteStatus($viewer->getPHID()); $status_invited = PhabricatorCalendarEventInvitee::STATUS_INVITED; $is_invite_pending = ($invite_status == $status_invited); $header = id(new PHUIHeaderView()) ->setUser($viewer) ->setHeader($event->getName()) ->setStatus($icon, $color, $status) ->setPolicyObject($event) ->setHeaderIcon('fa-calendar'); if ($is_invite_pending) { $decline_button = id(new PHUIButtonView()) ->setTag('a') ->setIcon('fa-times grey') ->setHref($this->getApplicationURI("/event/decline/{$id}/")) ->setWorkflow(true) ->setText(pht('Decline')); $accept_button = id(new PHUIButtonView()) ->setTag('a') ->setIcon('fa-check green') ->setHref($this->getApplicationURI("/event/accept/{$id}/")) ->setWorkflow(true) ->setText(pht('Accept')); $header->addActionLink($decline_button) ->addActionLink($accept_button); } return $header; } - private function buildActionView(PhabricatorCalendarEvent $event) { + private function buildCurtain(PhabricatorCalendarEvent $event) { $viewer = $this->getRequest()->getUser(); $id = $event->getID(); $is_cancelled = $event->getIsCancelled(); $is_attending = $event->getIsUserAttending($viewer->getPHID()); - $actions = id(new PhabricatorActionListView()) - ->setUser($viewer) - ->setObject($event); - $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $event, PhabricatorPolicyCapability::CAN_EDIT); $edit_label = false; $edit_uri = false; if ($event->getIsGhostEvent()) { $index = $event->getSequenceIndex(); $edit_label = pht('Edit This Instance'); $edit_uri = "event/edit/{$id}/{$index}/"; } else if ($event->getIsRecurrenceException()) { $edit_label = pht('Edit This Instance'); $edit_uri = "event/edit/{$id}/"; } else { $edit_label = pht('Edit'); $edit_uri = "event/edit/{$id}/"; } + $curtain = $this->newCurtainView($event); + if ($edit_label && $edit_uri) { - $actions->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName($edit_label) ->setIcon('fa-pencil') ->setHref($this->getApplicationURI($edit_uri)) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); } if ($is_attending) { - $actions->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Decline Event')) ->setIcon('fa-user-times') ->setHref($this->getApplicationURI("event/join/{$id}/")) ->setWorkflow(true)); } else { - $actions->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Join Event')) ->setIcon('fa-user-plus') ->setHref($this->getApplicationURI("event/join/{$id}/")) ->setWorkflow(true)); } $cancel_uri = $this->getApplicationURI("event/cancel/{$id}/"); if ($event->getIsGhostEvent()) { $index = $event->getSequenceIndex(); $can_reinstate = $event->getIsParentCancelled(); $cancel_label = pht('Cancel This Instance'); $reinstate_label = pht('Reinstate This Instance'); $cancel_disabled = (!$can_edit || $can_reinstate); $cancel_uri = $this->getApplicationURI("event/cancel/{$id}/{$index}/"); } else if ($event->getIsRecurrenceException()) { $can_reinstate = $event->getIsParentCancelled(); $cancel_label = pht('Cancel This Instance'); $reinstate_label = pht('Reinstate This Instance'); $cancel_disabled = (!$can_edit || $can_reinstate); } else if ($event->getIsRecurrenceParent()) { $cancel_label = pht('Cancel Recurrence'); $reinstate_label = pht('Reinstate Recurrence'); $cancel_disabled = !$can_edit; } else { $cancel_label = pht('Cancel Event'); $reinstate_label = pht('Reinstate Event'); $cancel_disabled = !$can_edit; } if ($is_cancelled) { - $actions->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName($reinstate_label) ->setIcon('fa-plus') ->setHref($cancel_uri) ->setDisabled($cancel_disabled) ->setWorkflow(true)); } else { - $actions->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName($cancel_label) ->setIcon('fa-times') ->setHref($cancel_uri) ->setDisabled($cancel_disabled) ->setWorkflow(true)); } - return $actions; - } - - private function buildPropertyListView( - PhabricatorCalendarEvent $event) { - $viewer = $this->getViewer(); - - $properties = id(new PHUIPropertyListView()) - ->setUser($viewer) - ->setObject($event); - - $properties->invokeWillRenderEvent(); - - return $properties; + return $curtain; } private function buildPropertySection( PhabricatorCalendarEvent $event) { $viewer = $this->getViewer(); $properties = id(new PHUIPropertyListView()) ->setUser($viewer); if ($event->getIsAllDay()) { $date_start = phabricator_date($event->getDateFrom(), $viewer); $date_end = phabricator_date($event->getDateTo(), $viewer); if ($date_start == $date_end) { $properties->addProperty( pht('Time'), phabricator_date($event->getDateFrom(), $viewer)); } else { $properties->addProperty( pht('Starts'), phabricator_date($event->getDateFrom(), $viewer)); $properties->addProperty( pht('Ends'), phabricator_date($event->getDateTo(), $viewer)); } } else { $properties->addProperty( pht('Starts'), phabricator_datetime($event->getDateFrom(), $viewer)); $properties->addProperty( pht('Ends'), phabricator_datetime($event->getDateTo(), $viewer)); } if ($event->getIsRecurring()) { $properties->addProperty( pht('Recurs'), ucwords(idx($event->getRecurrenceFrequency(), 'rule'))); if ($event->getRecurrenceEndDate()) { $properties->addProperty( pht('Recurrence Ends'), phabricator_datetime($event->getRecurrenceEndDate(), $viewer)); } if ($event->getInstanceOfEventPHID()) { $properties->addProperty( pht('Recurrence of Event'), pht('%s of %s', $event->getSequenceIndex(), $viewer->renderHandle($event->getInstanceOfEventPHID())->render())); } } $properties->addProperty( pht('Host'), $viewer->renderHandle($event->getUserPHID())); $invitees = $event->getInvitees(); foreach ($invitees as $key => $invitee) { if ($invitee->isUninvited()) { unset($invitees[$key]); } } if ($invitees) { $invitee_list = new PHUIStatusListView(); $icon_invited = PHUIStatusItemView::ICON_OPEN; $icon_attending = PHUIStatusItemView::ICON_ACCEPT; $icon_declined = PHUIStatusItemView::ICON_REJECT; $status_invited = PhabricatorCalendarEventInvitee::STATUS_INVITED; $status_attending = PhabricatorCalendarEventInvitee::STATUS_ATTENDING; $status_declined = PhabricatorCalendarEventInvitee::STATUS_DECLINED; $icon_map = array( $status_invited => $icon_invited, $status_attending => $icon_attending, $status_declined => $icon_declined, ); $icon_color_map = array( $status_invited => null, $status_attending => 'green', $status_declined => 'red', ); foreach ($invitees as $invitee) { $item = new PHUIStatusItemView(); $invitee_phid = $invitee->getInviteePHID(); $status = $invitee->getStatus(); $target = $viewer->renderHandle($invitee_phid); $icon = $icon_map[$status]; $icon_color = $icon_color_map[$status]; $item->setIcon($icon, $icon_color) ->setTarget($target); $invitee_list->addItem($item); } } else { $invitee_list = phutil_tag( 'em', array(), pht('None')); } $properties->addProperty( pht('Invitees'), $invitee_list); $properties->invokeWillRenderEvent(); $properties->addProperty( pht('Icon'), id(new PhabricatorCalendarIconSet()) ->getIconLabel($event->getIcon())); return $properties; } private function buildDescriptionView( PhabricatorCalendarEvent $event) { $viewer = $this->getViewer(); $properties = id(new PHUIPropertyListView()) ->setUser($viewer); if (strlen($event->getDescription())) { $description = new PHUIRemarkupView($viewer, $event->getDescription()); $properties->addTextContent($description); return $properties; } return null; } } diff --git a/src/applications/countdown/controller/PhabricatorCountdownViewController.php b/src/applications/countdown/controller/PhabricatorCountdownViewController.php index 9a983f0ed9..6e259df555 100644 --- a/src/applications/countdown/controller/PhabricatorCountdownViewController.php +++ b/src/applications/countdown/controller/PhabricatorCountdownViewController.php @@ -1,177 +1,159 @@ getViewer(); $id = $request->getURIData('id'); $countdown = id(new PhabricatorCountdownQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$countdown) { return new Aphront404Response(); } $countdown_view = id(new PhabricatorCountdownView()) ->setUser($viewer) ->setCountdown($countdown); $id = $countdown->getID(); $title = $countdown->getTitle(); $crumbs = $this ->buildApplicationCrumbs() ->addTextCrumb("C{$id}") ->setBorder(true); $epoch = $countdown->getEpoch(); if ($epoch >= PhabricatorTime::getNow()) { $icon = 'fa-clock-o'; $color = ''; $status = pht('Running'); } else { $icon = 'fa-check-square-o'; $color = 'dark'; $status = pht('Launched'); } $header = id(new PHUIHeaderView()) ->setHeader($title) ->setUser($viewer) ->setPolicyObject($countdown) ->setStatus($icon, $color, $status) ->setHeaderIcon('fa-rocket'); - $actions = $this->buildActionListView($countdown); - $properties = $this->buildPropertyListView($countdown); + $curtain = $this->buildCurtain($countdown); $subheader = $this->buildSubheaderView($countdown); $timeline = $this->buildTransactionTimeline( $countdown, new PhabricatorCountdownTransactionQuery()); $add_comment = $this->buildCommentForm($countdown); $content = array( $countdown_view, $timeline, $add_comment, ); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setSubheader($subheader) - ->setMainColumn($content) - ->setPropertyList($properties) - ->setActionList($actions); + ->setCurtain($curtain) + ->setMainColumn($content); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->setPageObjectPHIDs( array( $countdown->getPHID(), )) - ->appendChild( - array( - $view, - )); + ->appendChild($view); } - private function buildActionListView(PhabricatorCountdown $countdown) { - $request = $this->getRequest(); - $viewer = $request->getUser(); + private function buildCurtain(PhabricatorCountdown $countdown) { + $viewer = $this->getViewer(); $id = $countdown->getID(); - $view = id(new PhabricatorActionListView()) - ->setObject($countdown) - ->setUser($viewer); - $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $countdown, PhabricatorPolicyCapability::CAN_EDIT); - $view->addAction( + $curtain = $this->newCurtainView($countdown); + + $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Edit Countdown')) ->setHref($this->getApplicationURI("edit/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-times') ->setName(pht('Delete Countdown')) ->setHref($this->getApplicationURI("delete/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow(true)); - return $view; - } - - private function buildPropertyListView( - PhabricatorCountdown $countdown) { - $viewer = $this->getViewer(); - $view = id(new PHUIPropertyListView()) - ->setUser($viewer) - ->setObject($countdown); - $view->invokeWillRenderEvent(); - return $view; + return $curtain; } private function buildSubheaderView( PhabricatorCountdown $countdown) { $viewer = $this->getViewer(); $author = $viewer->renderHandle($countdown->getAuthorPHID())->render(); $date = phabricator_datetime($countdown->getDateCreated(), $viewer); $author = phutil_tag('strong', array(), $author); $person = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) ->withPHIDs(array($countdown->getAuthorPHID())) ->needProfileImage(true) ->executeOne(); $image_uri = $person->getProfileImageURI(); $image_href = '/p/'.$person->getUsername(); $content = pht('Authored by %s on %s.', $author, $date); return id(new PHUIHeadThingView()) ->setImage($image_uri) ->setImageHref($image_href) ->setContent($content); } private function buildCommentForm(PhabricatorCountdown $countdown) { $viewer = $this->getViewer(); $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); $add_comment_header = $is_serious ? pht('Add Comment') : pht('Last Words'); $draft = PhabricatorDraft::newFromUserAndKey( $viewer, $countdown->getPHID()); return id(new PhabricatorApplicationTransactionCommentView()) ->setUser($viewer) ->setObjectPHID($countdown->getPHID()) ->setDraft($draft) ->setHeaderText($add_comment_header) ->setAction($this->getApplicationURI('/comment/'.$countdown->getID().'/')) ->setSubmitButtonName(pht('Add Comment')); } } diff --git a/src/applications/fund/controller/FundInitiativeViewController.php b/src/applications/fund/controller/FundInitiativeViewController.php index f4535d574e..a416054ae3 100644 --- a/src/applications/fund/controller/FundInitiativeViewController.php +++ b/src/applications/fund/controller/FundInitiativeViewController.php @@ -1,181 +1,163 @@ getViewer(); $id = $request->getURIData('id'); $initiative = id(new FundInitiativeQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$initiative) { return new Aphront404Response(); } $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($initiative->getMonogram()); $crumbs->setBorder(true); $title = pht( '%s %s', $initiative->getMonogram(), $initiative->getName()); if ($initiative->isClosed()) { $status_icon = 'fa-times'; $status_color = 'bluegrey'; } else { $status_icon = 'fa-check'; $status_color = 'bluegrey'; } $status_name = idx( FundInitiative::getStatusNameMap(), $initiative->getStatus()); $header = id(new PHUIHeaderView()) ->setHeader($initiative->getName()) ->setUser($viewer) ->setPolicyObject($initiative) ->setStatus($status_icon, $status_color, $status_name) ->setHeaderIcon('fa-heart'); - $properties = $this->buildPropertyListView($initiative); - $actions = $this->buildActionListView($initiative); + $curtain = $this->buildCurtain($initiative); $details = $this->buildPropertySectionView($initiative); $timeline = $this->buildTransactionTimeline( $initiative, new FundInitiativeTransactionQuery()); $timeline->setShouldTerminate(true); $view = id(new PHUITwoColumnView()) ->setHeader($header) + ->setCurtain($curtain) ->setMainColumn($timeline) - ->setPropertyList($properties) - ->addPropertySection(pht('DETAILS'), $details) - ->setActionList($actions); + ->addPropertySection(pht('DETAILS'), $details); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->setPageObjectPHIDs(array($initiative->getPHID())) - ->appendChild( - array( - $view, - )); - } - - private function buildPropertyListView(FundInitiative $initiative) { - $viewer = $this->getRequest()->getUser(); - - $view = id(new PHUIPropertyListView()) - ->setUser($viewer) - ->setObject($initiative); - - $view->invokeWillRenderEvent(); - - return $view; + ->appendChild($view); } private function buildPropertySectionView(FundInitiative $initiative) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer); $owner_phid = $initiative->getOwnerPHID(); $merchant_phid = $initiative->getMerchantPHID(); $view->addProperty( pht('Owner'), $viewer->renderHandle($owner_phid)); $view->addProperty( pht('Payable to Merchant'), $viewer->renderHandle($merchant_phid)); $view->addProperty( pht('Total Funding'), $initiative->getTotalAsCurrency()->formatForDisplay()); $description = $initiative->getDescription(); if (strlen($description)) { $description = new PHUIRemarkupView($viewer, $description); $view->addSectionHeader( pht('Description'), PHUIPropertyListView::ICON_SUMMARY); $view->addTextContent($description); } $risks = $initiative->getRisks(); if (strlen($risks)) { $risks = new PHUIRemarkupView($viewer, $risks); $view->addSectionHeader( pht('Risks/Challenges'), 'fa-ambulance'); $view->addTextContent($risks); } return $view; } - private function buildActionListView(FundInitiative $initiative) { - $viewer = $this->getRequest()->getUser(); + private function buildCurtain(FundInitiative $initiative) { + $viewer = $this->getViewer(); + $id = $initiative->getID(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $initiative, PhabricatorPolicyCapability::CAN_EDIT); - $view = id(new PhabricatorActionListView()) - ->setUser($viewer) - ->setObject($initiative); + $curtain = $this->newCurtainView($initiative); - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Initiative')) ->setIcon('fa-pencil') ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit) ->setHref($this->getApplicationURI("/edit/{$id}/"))); if ($initiative->isClosed()) { $close_name = pht('Reopen Initiative'); $close_icon = 'fa-check'; } else { $close_name = pht('Close Initiative'); $close_icon = 'fa-times'; } - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName($close_name) ->setIcon($close_icon) ->setDisabled(!$can_edit) ->setWorkflow(true) ->setHref($this->getApplicationURI("/close/{$id}/"))); - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Back Initiative')) ->setIcon('fa-money') ->setDisabled($initiative->isClosed()) ->setWorkflow(true) ->setHref($this->getApplicationURI("/back/{$id}/"))); - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('View Backers')) ->setIcon('fa-bank') ->setHref($this->getApplicationURI("/backers/{$id}/"))); - return $view; + return $curtain; } } diff --git a/src/applications/herald/controller/HeraldRuleViewController.php b/src/applications/herald/controller/HeraldRuleViewController.php index 4036be250b..f5e058d3f3 100644 --- a/src/applications/herald/controller/HeraldRuleViewController.php +++ b/src/applications/herald/controller/HeraldRuleViewController.php @@ -1,181 +1,158 @@ getViewer(); $id = $request->getURIData('id'); $rule = id(new HeraldRuleQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needConditionsAndActions(true) ->executeOne(); if (!$rule) { return new Aphront404Response(); } $header = id(new PHUIHeaderView()) ->setUser($viewer) ->setHeader($rule->getName()) ->setPolicyObject($rule) ->setHeaderIcon('fa-bullhorn'); if ($rule->getIsDisabled()) { $header->setStatus( 'fa-ban', 'red', pht('Archived')); } else { $header->setStatus( 'fa-check', 'bluegrey', pht('Active')); } - $actions = $this->buildActionView($rule); - $properties = $this->buildPropertyView($rule); + $curtain = $this->buildCurtain($rule); $details = $this->buildPropertySectionView($rule); $description = $this->buildDescriptionView($rule); $id = $rule->getID(); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb("H{$id}"); $crumbs->setBorder(true); - $object_box = id(new PHUIObjectBoxView()) - ->setHeader($header) - ->addPropertyList($properties); - $timeline = $this->buildTransactionTimeline( $rule, new HeraldTransactionQuery()); $timeline->setShouldTerminate(true); $title = $rule->getName(); $view = id(new PHUITwoColumnView()) ->setHeader($header) + ->setCurtain($curtain) ->setMainColumn($timeline) ->addPropertySection(pht('DETAILS'), $details) - ->addPropertySection(pht('DESCRIPTION'), $description) - ->setPropertyList($properties) - ->setActionList($actions); + ->addPropertySection(pht('DESCRIPTION'), $description); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) - ->appendChild( - array( - $view, - )); + ->appendChild($view); } - private function buildActionView(HeraldRule $rule) { - $viewer = $this->getRequest()->getUser(); - $id = $rule->getID(); + private function buildCurtain(HeraldRule $rule) { + $viewer = $this->getViewer(); - $view = id(new PhabricatorActionListView()) - ->setUser($viewer) - ->setObject($rule); + $id = $rule->getID(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $rule, PhabricatorPolicyCapability::CAN_EDIT); - $view->addAction( + $curtain = $this->newCurtainView($rule); + + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Rule')) ->setHref($this->getApplicationURI("edit/{$id}/")) ->setIcon('fa-pencil') ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); if ($rule->getIsDisabled()) { $disable_uri = "disable/{$id}/enable/"; $disable_icon = 'fa-check'; $disable_name = pht('Activate Rule'); } else { $disable_uri = "disable/{$id}/disable/"; $disable_icon = 'fa-ban'; $disable_name = pht('Archive Rule'); } - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Disable Rule')) ->setHref($this->getApplicationURI($disable_uri)) ->setIcon($disable_icon) ->setName($disable_name) ->setDisabled(!$can_edit) ->setWorkflow(true)); - return $view; - } - - private function buildPropertyView( - HeraldRule $rule) { - - $viewer = $this->getRequest()->getUser(); - $view = id(new PHUIPropertyListView()) - ->setUser($viewer) - ->setObject($rule); - - $view->invokeWillRenderEvent(); - - return $view; + return $curtain; } - private function buildPropertySectionView( + private function buildPropertySectionView( HeraldRule $rule) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer); $view->addProperty( pht('Rule Type'), idx(HeraldRuleTypeConfig::getRuleTypeMap(), $rule->getRuleType())); if ($rule->isPersonalRule()) { $view->addProperty( pht('Author'), $viewer->renderHandle($rule->getAuthorPHID())); } $adapter = HeraldAdapter::getAdapterForContentType($rule->getContentType()); if ($adapter) { $view->addProperty( pht('Applies To'), idx( HeraldAdapter::getEnabledAdapterMap($viewer), $rule->getContentType())); if ($rule->isObjectRule()) { $view->addProperty( pht('Trigger Object'), $viewer->renderHandle($rule->getTriggerObjectPHID())); } } return $view; } private function buildDescriptionView(HeraldRule $rule) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer); $adapter = HeraldAdapter::getAdapterForContentType($rule->getContentType()); if ($adapter) { $handles = $viewer->loadHandles(HeraldAdapter::getHandlePHIDs($rule)); $rule_text = $adapter->renderRuleAsText($rule, $handles, $viewer); $view->addTextContent($rule_text); return $view; } return null; } } diff --git a/src/applications/macro/controller/PhabricatorMacroViewController.php b/src/applications/macro/controller/PhabricatorMacroViewController.php index 9ee70eecdc..8c12e5528a 100644 --- a/src/applications/macro/controller/PhabricatorMacroViewController.php +++ b/src/applications/macro/controller/PhabricatorMacroViewController.php @@ -1,222 +1,202 @@ getViewer(); $id = $request->getURIData('id'); $macro = id(new PhabricatorMacroQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needFiles(true) ->executeOne(); if (!$macro) { return new Aphront404Response(); } $title_short = pht('Macro "%s"', $macro->getName()); $title_long = pht('Image Macro "%s"', $macro->getName()); - $actions = $this->buildActionView($macro); + $curtain = $this->buildCurtain($macro); $subheader = $this->buildSubheaderView($macro); - $properties = $this->buildPropertyView($macro); $file = $this->buildFileView($macro); $details = $this->buildPropertySectionView($macro); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($macro->getName()); $crumbs->setBorder(true); $timeline = $this->buildTransactionTimeline( $macro, new PhabricatorMacroTransactionQuery()); $header = id(new PHUIHeaderView()) ->setUser($viewer) ->setPolicyObject($macro) ->setHeader($macro->getName()) ->setHeaderIcon('fa-file-image-o'); if (!$macro->getIsDisabled()) { $header->setStatus('fa-check', 'bluegrey', pht('Active')); } else { $header->setStatus('fa-ban', 'red', pht('Archived')); } $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); $comment_header = $is_serious ? pht('Add Comment') : pht('Grovel in Awe'); $draft = PhabricatorDraft::newFromUserAndKey($viewer, $macro->getPHID()); $add_comment_form = id(new PhabricatorApplicationTransactionCommentView()) ->setUser($viewer) ->setObjectPHID($macro->getPHID()) ->setDraft($draft) ->setHeaderText($comment_header) ->setAction($this->getApplicationURI('/comment/'.$macro->getID().'/')) ->setSubmitButtonName(pht('Add Comment')); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setSubheader($subheader) + ->setCurtain($curtain) ->setMainColumn(array( $timeline, $add_comment_form, )) ->addPropertySection(pht('MACRO'), $file) - ->addPropertySection(pht('DETAILS'), $details) - ->setPropertyList($properties) - ->setActionList($actions); + ->addPropertySection(pht('DETAILS'), $details); return $this->newPage() ->setTitle($title_short) ->setCrumbs($crumbs) ->setPageObjectPHIDs(array($macro->getPHID())) - ->appendChild( - array( - $view, - )); + ->appendChild($view); } - private function buildActionView( + private function buildCurtain( PhabricatorFileImageMacro $macro) { $can_manage = $this->hasApplicationCapability( PhabricatorMacroManageCapability::CAPABILITY); - $request = $this->getRequest(); - $view = id(new PhabricatorActionListView()) - ->setUser($request->getUser()) - ->setObject($macro) - ->addAction( + $curtain = $this->newCurtainView($macro); + + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Macro')) ->setHref($this->getApplicationURI('/edit/'.$macro->getID().'/')) ->setDisabled(!$can_manage) ->setWorkflow(!$can_manage) ->setIcon('fa-pencil')); - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Audio')) ->setHref($this->getApplicationURI('/audio/'.$macro->getID().'/')) ->setDisabled(!$can_manage) ->setWorkflow(!$can_manage) ->setIcon('fa-music')); if ($macro->getIsDisabled()) { - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Activate Macro')) ->setHref($this->getApplicationURI('/disable/'.$macro->getID().'/')) ->setWorkflow(true) ->setDisabled(!$can_manage) ->setIcon('fa-check')); } else { - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Archive Macro')) ->setHref($this->getApplicationURI('/disable/'.$macro->getID().'/')) ->setWorkflow(true) ->setDisabled(!$can_manage) ->setIcon('fa-ban')); } - return $view; + return $curtain; } private function buildSubheaderView( PhabricatorFileImageMacro $macro) { $viewer = $this->getViewer(); $author_phid = $macro->getAuthorPHID(); $author = $viewer->renderHandle($author_phid)->render(); $date = phabricator_datetime($macro->getDateCreated(), $viewer); $author = phutil_tag('strong', array(), $author); $handles = $viewer->loadHandles(array($author_phid)); $image_uri = $handles[$author_phid]->getImageURI(); $image_href = $handles[$author_phid]->getURI(); $content = pht('Masterfully imagined by %s on %s.', $author, $date); return id(new PHUIHeadThingView()) ->setImage($image_uri) ->setImageHref($image_href) ->setContent($content); } private function buildPropertySectionView( PhabricatorFileImageMacro $macro) { $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView()) ->setUser($viewer); switch ($macro->getAudioBehavior()) { case PhabricatorFileImageMacro::AUDIO_BEHAVIOR_ONCE: $view->addProperty(pht('Audio Behavior'), pht('Play Once')); break; case PhabricatorFileImageMacro::AUDIO_BEHAVIOR_LOOP: $view->addProperty(pht('Audio Behavior'), pht('Loop')); break; } $audio_phid = $macro->getAudioPHID(); if ($audio_phid) { $view->addProperty( pht('Audio'), $viewer->renderHandle($audio_phid)); } if ($view->hasAnyProperties()) { return $view; } return null; } private function buildFileView( PhabricatorFileImageMacro $macro) { $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView()) ->setUser($viewer); $file = $macro->getFile(); if ($file) { $view->addImageContent( phutil_tag( 'img', array( 'src' => $file->getViewURI(), 'class' => 'phabricator-image-macro-hero', ))); return $view; } return null; } - private function buildPropertyView( - PhabricatorFileImageMacro $macro) { - $viewer = $this->getViewer(); - - $view = id(new PHUIPropertyListView()) - ->setUser($this->getRequest()->getUser()) - ->setObject($macro); - - $view->invokeWillRenderEvent(); - - return $view; - } - } diff --git a/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php b/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php index 07dea613db..443a7e37d3 100644 --- a/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php +++ b/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php @@ -1,213 +1,211 @@ getViewer(); $application = $request->getURIData('application'); $selected = id(new PhabricatorApplicationQuery()) ->setViewer($viewer) ->withClasses(array($application)) ->executeOne(); if (!$selected) { return new Aphront404Response(); } $title = $selected->getName(); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($selected->getName()); $crumbs->setBorder(true); $header = id(new PHUIHeaderView()) ->setHeader($title) ->setUser($viewer) ->setPolicyObject($selected) ->setHeaderIcon($selected->getIcon()); if ($selected->isInstalled()) { $header->setStatus('fa-check', 'bluegrey', pht('Installed')); } else { $header->setStatus('fa-ban', 'dark', pht('Uninstalled')); } - $actions = $this->buildActionView($viewer, $selected); + $curtain = $this->buildCurtain($selected); $details = $this->buildPropertySectionView($selected); $policies = $this->buildPolicyView($selected); $configs = PhabricatorApplicationConfigurationPanel::loadAllPanelsForApplication( $selected); $panels = array(); foreach ($configs as $config) { $config->setViewer($viewer); $config->setApplication($selected); $panel = $config->buildConfigurationPagePanel(); $panel->setBackground(PHUIObjectBoxView::BLUE_PROPERTY); $panels[] = $panel; } $view = id(new PHUITwoColumnView()) ->setHeader($header) + ->setCurtain($curtain) ->setMainColumn(array( $policies, $panels, )) - ->addPropertySection(pht('DETAILS'), $details) - ->setActionList($actions); + ->addPropertySection(pht('DETAILS'), $details); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild( array( $view, )); } private function buildPropertySectionView( PhabricatorApplication $application) { $viewer = $this->getViewer(); $properties = id(new PHUIPropertyListView()); $properties->addProperty( pht('Description'), $application->getShortDescription()); if ($application->getFlavorText()) { $properties->addProperty( null, phutil_tag('em', array(), $application->getFlavorText())); } if ($application->isPrototype()) { $proto_href = PhabricatorEnv::getDoclink( 'User Guide: Prototype Applications'); $learn_more = phutil_tag( 'a', array( 'href' => $proto_href, 'target' => '_blank', ), pht('Learn More')); $properties->addProperty( pht('Prototype'), pht( 'This application is a prototype. %s', $learn_more)); } $overview = $application->getOverview(); if (strlen($overview)) { $overview = new PHUIRemarkupView($viewer, $overview); $properties->addSectionHeader( pht('Overview'), PHUIPropertyListView::ICON_SUMMARY); $properties->addTextContent($overview); } return $properties; } private function buildPolicyView( PhabricatorApplication $application) { $viewer = $this->getViewer(); $properties = id(new PHUIPropertyListView()) ->setStacked(true); $header = id(new PHUIHeaderView()) ->setHeader(pht('POLICIES')) ->setHeaderIcon('fa-lock'); $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( $viewer, $application); foreach ($application->getCapabilities() as $capability) { $properties->addProperty( $application->getCapabilityLabel($capability), idx($descriptions, $capability)); } return id(new PHUIObjectBoxView()) ->setHeader($header) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->appendChild($properties); } - private function buildActionView( - PhabricatorUser $user, - PhabricatorApplication $selected) { - - $view = id(new PhabricatorActionListView()) - ->setUser($user); + private function buildCurtain(PhabricatorApplication $application) { + $viewer = $this->getViewer(); $can_edit = PhabricatorPolicyFilter::hasCapability( - $user, - $selected, + $viewer, + $application, PhabricatorPolicyCapability::CAN_EDIT); - $edit_uri = $this->getApplicationURI('edit/'.get_class($selected).'/'); + $key = get_class($application); + $edit_uri = $this->getApplicationURI("edit/{$key}/"); + $install_uri = $this->getApplicationURI("{$key}/install/"); + $uninstall_uri = $this->getApplicationURI("{$key}/uninstall/"); + + $curtain = $this->newCurtainView($application); - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Policies')) ->setIcon('fa-pencil') ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit) ->setHref($edit_uri)); - if ($selected->canUninstall()) { - if ($selected->isInstalled()) { - $view->addAction( + if ($application->canUninstall()) { + if ($application->isInstalled()) { + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Uninstall')) ->setIcon('fa-times') ->setDisabled(!$can_edit) ->setWorkflow(true) - ->setHref( - $this->getApplicationURI(get_class($selected).'/uninstall/'))); + ->setHref($uninstall_uri)); } else { $action = id(new PhabricatorActionView()) ->setName(pht('Install')) ->setIcon('fa-plus') ->setDisabled(!$can_edit) ->setWorkflow(true) - ->setHref( - $this->getApplicationURI(get_class($selected).'/install/')); + ->setHref($install_uri); $prototypes_enabled = PhabricatorEnv::getEnvConfig( 'phabricator.show-prototypes'); - if ($selected->isPrototype() && !$prototypes_enabled) { + if ($application->isPrototype() && !$prototypes_enabled) { $action->setDisabled(true); } - $view->addAction($action); + $curtain->addAction($action); } } else { - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Uninstall')) ->setIcon('fa-times') ->setWorkflow(true) ->setDisabled(true) - ->setHref( - $this->getApplicationURI(get_class($selected).'/uninstall/'))); + ->setHref($uninstall_uri)); } - return $view; + return $curtain; } } diff --git a/src/applications/owners/controller/PhabricatorOwnersDetailController.php b/src/applications/owners/controller/PhabricatorOwnersDetailController.php index 9b2da6c3c1..5da36ad473 100644 --- a/src/applications/owners/controller/PhabricatorOwnersDetailController.php +++ b/src/applications/owners/controller/PhabricatorOwnersDetailController.php @@ -1,352 +1,332 @@ getViewer(); $package = id(new PhabricatorOwnersPackageQuery()) ->setViewer($viewer) ->withIDs(array($request->getURIData('id'))) ->needPaths(true) ->executeOne(); if (!$package) { return new Aphront404Response(); } $paths = $package->getPaths(); $repository_phids = array(); foreach ($paths as $path) { $repository_phids[$path->getRepositoryPHID()] = true; } if ($repository_phids) { $repositories = id(new PhabricatorRepositoryQuery()) ->setViewer($viewer) ->withPHIDs(array_keys($repository_phids)) ->execute(); $repositories = mpull($repositories, null, 'getPHID'); } else { $repositories = array(); } $field_list = PhabricatorCustomField::getObjectFields( $package, PhabricatorCustomField::ROLE_VIEW); $field_list ->setViewer($viewer) ->readFieldsFromStorage($package); - $actions = $this->buildPackageActionView($package); - $properties = $this->buildPackagePropertyView($package, $field_list); + $curtain = $this->buildCurtain($package); $details = $this->buildPackageDetailView($package, $field_list); if ($package->isArchived()) { $header_icon = 'fa-ban'; $header_name = pht('Archived'); $header_color = 'dark'; } else { $header_icon = 'fa-check'; $header_name = pht('Active'); $header_color = 'bluegrey'; } $header = id(new PHUIHeaderView()) ->setUser($viewer) ->setHeader($package->getName()) ->setStatus($header_icon, $header_color, $header_name) ->setPolicyObject($package) ->setHeaderIcon('fa-gift'); $commit_views = array(); $commit_uri = id(new PhutilURI('/audit/')) ->setQueryParams( array( 'auditorPHIDs' => $package->getPHID(), )); $status_concern = DiffusionCommitQuery::AUDIT_STATUS_CONCERN; $attention_commits = id(new DiffusionCommitQuery()) ->setViewer($request->getUser()) ->withAuditorPHIDs(array($package->getPHID())) ->withAuditStatus($status_concern) ->needCommitData(true) ->setLimit(10) ->execute(); $view = id(new PhabricatorAuditListView()) ->setUser($viewer) ->setNoDataString(pht('This package has no open problem commits.')) ->setCommits($attention_commits); $commit_views[] = array( 'view' => $view, 'header' => pht('Needs Attention'), 'icon' => 'fa-warning', 'button' => id(new PHUIButtonView()) ->setTag('a') ->setHref($commit_uri->alter('status', $status_concern)) ->setIcon('fa-list-ul') ->setText(pht('View All')), ); $all_commits = id(new DiffusionCommitQuery()) ->setViewer($request->getUser()) ->withAuditorPHIDs(array($package->getPHID())) ->needCommitData(true) ->setLimit(100) ->execute(); $view = id(new PhabricatorAuditListView()) ->setUser($viewer) ->setCommits($all_commits) ->setNoDataString(pht('No commits in this package.')); $commit_views[] = array( 'view' => $view, 'header' => pht('Recent Commits'), 'icon' => 'fa-code', 'button' => id(new PHUIButtonView()) ->setTag('a') ->setHref($commit_uri) ->setIcon('fa-list-ul') ->setText(pht('View All')), ); $phids = array(); foreach ($commit_views as $commit_view) { $phids[] = $commit_view['view']->getRequiredHandlePHIDs(); } $phids = array_mergev($phids); $handles = $this->loadViewerHandles($phids); $commit_panels = array(); foreach ($commit_views as $commit_view) { $commit_panel = id(new PHUIObjectBoxView()) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY); $commit_header = id(new PHUIHeaderView()) ->setHeader($commit_view['header']) ->setHeaderIcon($commit_view['icon']); if (isset($commit_view['button'])) { $commit_header->addActionLink($commit_view['button']); } $commit_view['view']->setHandles($handles); $commit_panel->setHeader($commit_header); $commit_panel->appendChild($commit_view['view']); $commit_panels[] = $commit_panel; } $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($package->getName()); $crumbs->setBorder(true); $timeline = $this->buildTransactionTimeline( $package, new PhabricatorOwnersPackageTransactionQuery()); $timeline->setShouldTerminate(true); $view = id(new PHUITwoColumnView()) ->setHeader($header) + ->setCurtain($curtain) ->setMainColumn(array( $this->renderPathsTable($paths, $repositories), $commit_panels, $timeline, )) - ->addPropertySection(pht('Details'), $details) - ->setPropertyList($properties) - ->setActionList($actions); + ->addPropertySection(pht('Details'), $details); return $this->newPage() ->setTitle($package->getName()) ->setCrumbs($crumbs) - ->appendChild( - array( - $view, - )); - } - - private function buildPackagePropertyView( - PhabricatorOwnersPackage $package, - PhabricatorCustomFieldList $field_list) { - - $viewer = $this->getViewer(); - $view = id(new PHUIPropertyListView()) - ->setUser($viewer) - ->setObject($package); - $view->invokeWillRenderEvent(); - - return $view; + ->appendChild($view); } private function buildPackageDetailView( PhabricatorOwnersPackage $package, PhabricatorCustomFieldList $field_list) { $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView()) ->setUser($viewer); $owners = $package->getOwners(); if ($owners) { $owner_list = $viewer->renderHandleList(mpull($owners, 'getUserPHID')); } else { $owner_list = phutil_tag('em', array(), pht('None')); } $view->addProperty(pht('Owners'), $owner_list); if ($package->getAuditingEnabled()) { $auditing = pht('Enabled'); } else { $auditing = pht('Disabled'); } $view->addProperty(pht('Auditing'), $auditing); $description = $package->getDescription(); if (strlen($description)) { $description = new PHUIRemarkupView($viewer, $description); $view->addSectionHeader(pht('Description')); $view->addTextContent($description); } $field_list->appendFieldsToPropertyList( $package, $viewer, $view); return $view; } - private function buildPackageActionView(PhabricatorOwnersPackage $package) { + private function buildCurtain(PhabricatorOwnersPackage $package) { $viewer = $this->getViewer(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $package, PhabricatorPolicyCapability::CAN_EDIT); $id = $package->getID(); $edit_uri = $this->getApplicationURI("/edit/{$id}/"); $paths_uri = $this->getApplicationURI("/paths/{$id}/"); - $action_list = id(new PhabricatorActionListView()) - ->setUser($viewer) - ->setObject($package); + $curtain = $this->newCurtainView($package); - $action_list->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Edit Package')) - ->setIcon('fa-pencil') - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit) - ->setHref($edit_uri)); + $curtain->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Edit Package')) + ->setIcon('fa-pencil') + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit) + ->setHref($edit_uri)); if ($package->isArchived()) { - $action_list->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Activate Package')) - ->setIcon('fa-check') - ->setDisabled(!$can_edit) - ->setWorkflow($can_edit) - ->setHref($this->getApplicationURI("/archive/{$id}/"))); + $curtain->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Activate Package')) + ->setIcon('fa-check') + ->setDisabled(!$can_edit) + ->setWorkflow($can_edit) + ->setHref($this->getApplicationURI("/archive/{$id}/"))); } else { - $action_list->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Archive Package')) - ->setIcon('fa-ban') - ->setDisabled(!$can_edit) - ->setWorkflow($can_edit) - ->setHref($this->getApplicationURI("/archive/{$id}/"))); - } - - $action_list->addAction( + $curtain->addAction( id(new PhabricatorActionView()) - ->setName(pht('Edit Paths')) - ->setIcon('fa-folder-open') + ->setName(pht('Archive Package')) + ->setIcon('fa-ban') ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit) - ->setHref($paths_uri)); + ->setWorkflow($can_edit) + ->setHref($this->getApplicationURI("/archive/{$id}/"))); + } + + $curtain->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Edit Paths')) + ->setIcon('fa-folder-open') + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit) + ->setHref($paths_uri)); - return $action_list; + return $curtain; } private function renderPathsTable(array $paths, array $repositories) { $viewer = $this->getViewer(); $rows = array(); foreach ($paths as $path) { $repo = idx($repositories, $path->getRepositoryPHID()); if (!$repo) { continue; } $href = $repo->generateURI( array( 'branch' => $repo->getDefaultBranch(), 'path' => $path->getPath(), 'action' => 'browse', )); $path_link = phutil_tag( 'a', array( 'href' => (string)$href, ), $path->getPath()); $rows[] = array( ($path->getExcluded() ? '-' : '+'), $repo->getName(), $path_link, ); } $info = null; if (!$paths) { $info = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_WARNING) ->setErrors( array( pht( 'This package does not contain any paths yet. Use '. '"Edit Paths" to add some.'), )); } $table = id(new AphrontTableView($rows)) ->setHeaders( array( null, pht('Repository'), pht('Path'), )) ->setColumnClasses( array( null, null, 'wide', )); $header = id(new PHUIHeaderView()) ->setHeader(pht('Paths')) ->setHeaderIcon('fa-folder-open'); $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setTable($table); if ($info) { $box->setInfoView($info); } return $box; } } diff --git a/src/applications/passphrase/controller/PassphraseCredentialViewController.php b/src/applications/passphrase/controller/PassphraseCredentialViewController.php index fa52681d82..46bb13a688 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialViewController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialViewController.php @@ -1,252 +1,231 @@ getViewer(); $id = $request->getURIData('id'); $credential = id(new PassphraseCredentialQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$credential) { return new Aphront404Response(); } $type = PassphraseCredentialType::getTypeByConstant( $credential->getCredentialType()); if (!$type) { throw new Exception(pht('Credential has invalid type "%s"!', $type)); } $timeline = $this->buildTransactionTimeline( $credential, new PassphraseCredentialTransactionQuery()); $timeline->setShouldTerminate(true); $title = pht('%s %s', 'K'.$credential->getID(), $credential->getName()); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb('K'.$credential->getID()); $crumbs->setBorder(true); $header = $this->buildHeaderView($credential); - $actions = $this->buildActionView($credential, $type); - $properties = $this->buildPropertyView($credential, $type); + $curtain = $this->buildCurtain($credential, $type); $subheader = $this->buildSubheaderView($credential); $content = $this->buildPropertySectionView($credential, $type); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setSubheader($subheader) + ->setCurtain($curtain) ->setMainColumn($timeline) - ->addPropertySection(pht('PROPERTIES'), $content) - ->setPropertyList($properties) - ->setActionList($actions); + ->addPropertySection(pht('PROPERTIES'), $content); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) - ->appendChild( - array( - $view, - )); + ->appendChild($view); } private function buildHeaderView(PassphraseCredential $credential) { $viewer = $this->getRequest()->getUser(); $header = id(new PHUIHeaderView()) ->setUser($viewer) ->setHeader($credential->getName()) ->setPolicyObject($credential) ->setHeaderIcon('fa-user-secret'); if ($credential->getIsDestroyed()) { $header->setStatus('fa-ban', 'red', pht('Destroyed')); } return $header; } private function buildSubheaderView( PassphraseCredential $credential) { $viewer = $this->getViewer(); $author = $viewer->renderHandle($credential->getAuthorPHID())->render(); $date = phabricator_datetime($credential->getDateCreated(), $viewer); $author = phutil_tag('strong', array(), $author); $person = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) ->withPHIDs(array($credential->getAuthorPHID())) ->needProfileImage(true) ->executeOne(); if (!$person) { return null; } $image_uri = $person->getProfileImageURI(); $image_href = '/p/'.$credential->getUsername(); $content = pht('Created by %s on %s.', $author, $date); return id(new PHUIHeadThingView()) ->setImage($image_uri) ->setImageHref($image_href) ->setContent($content); } - private function buildActionView( + private function buildCurtain( PassphraseCredential $credential, PassphraseCredentialType $type) { - $viewer = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $id = $credential->getID(); $is_locked = $credential->getIsLocked(); if ($is_locked) { $credential_lock_text = pht('Locked Permanently'); $credential_lock_icon = 'fa-lock'; } else { $credential_lock_text = pht('Lock Permanently'); $credential_lock_icon = 'fa-unlock'; } $allow_conduit = $credential->getAllowConduit(); if ($allow_conduit) { $credential_conduit_text = pht('Prevent Conduit Access'); $credential_conduit_icon = 'fa-ban'; } else { $credential_conduit_text = pht('Allow Conduit Access'); $credential_conduit_icon = 'fa-wrench'; } - $actions = id(new PhabricatorActionListView()) - ->setObject($credential) - ->setUser($viewer); - $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $credential, PhabricatorPolicyCapability::CAN_EDIT); - $actions->addAction( + $curtain = $this->newCurtainView($credential); + + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Credential')) ->setIcon('fa-pencil') ->setHref($this->getApplicationURI("edit/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); if (!$credential->getIsDestroyed()) { - $actions->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Destroy Credential')) ->setIcon('fa-times') ->setHref($this->getApplicationURI("destroy/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow(true)); - $actions->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Show Secret')) ->setIcon('fa-eye') ->setHref($this->getApplicationURI("reveal/{$id}/")) ->setDisabled(!$can_edit || $is_locked) ->setWorkflow(true)); if ($type->hasPublicKey()) { - $actions->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Show Public Key')) ->setIcon('fa-download') ->setHref($this->getApplicationURI("public/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow(true)); } - $actions->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName($credential_conduit_text) ->setIcon($credential_conduit_icon) ->setHref($this->getApplicationURI("conduit/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow(true)); - $actions->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName($credential_lock_text) ->setIcon($credential_lock_icon) ->setHref($this->getApplicationURI("lock/{$id}/")) ->setDisabled(!$can_edit || $is_locked) ->setWorkflow(true)); } - - return $actions; + return $curtain; } private function buildPropertySectionView( PassphraseCredential $credential, PassphraseCredentialType $type) { $viewer = $this->getRequest()->getUser(); $properties = id(new PHUIPropertyListView()) ->setUser($viewer); $properties->addProperty( pht('Credential Type'), $type->getCredentialTypeName()); $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( $viewer, $credential); $properties->addProperty( pht('Editable By'), $descriptions[PhabricatorPolicyCapability::CAN_EDIT]); if ($type->shouldRequireUsername()) { $properties->addProperty( pht('Username'), $credential->getUsername()); } $used_by_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( $credential->getPHID(), PhabricatorCredentialsUsedByObjectEdgeType::EDGECONST); if ($used_by_phids) { $properties->addProperty( pht('Used By'), $viewer->renderHandleList($used_by_phids)); } $description = $credential->getDescription(); if (strlen($description)) { $properties->addSectionHeader( pht('Description'), PHUIPropertyListView::ICON_SUMMARY); $properties->addTextContent( new PHUIRemarkupView($viewer, $description)); } return $properties; } - private function buildPropertyView( - PassphraseCredential $credential, - PassphraseCredentialType $type) { - $viewer = $this->getRequest()->getUser(); - - $properties = id(new PHUIPropertyListView()) - ->setUser($viewer) - ->setObject($credential); - - $properties->invokeWillRenderEvent(); - return $properties; - } - } diff --git a/src/applications/ponder/controller/PonderQuestionViewController.php b/src/applications/ponder/controller/PonderQuestionViewController.php index 41819a34f0..a1105c6c8e 100644 --- a/src/applications/ponder/controller/PonderQuestionViewController.php +++ b/src/applications/ponder/controller/PonderQuestionViewController.php @@ -1,297 +1,276 @@ getViewer(); $id = $request->getURIData('id'); $question = id(new PonderQuestionQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needAnswers(true) ->needProjectPHIDs(true) ->executeOne(); if (!$question) { return new Aphront404Response(); } $answers = $this->buildAnswers($question); $answer_add_panel = id(new PonderAddAnswerView()) ->setQuestion($question) ->setUser($viewer) ->setActionURI('/ponder/answer/add/'); $header = new PHUIHeaderView(); $header->setHeader($question->getTitle()); $header->setUser($viewer); $header->setPolicyObject($question); $header->setHeaderIcon('fa-university'); if ($question->getStatus() == PonderQuestionStatus::STATUS_OPEN) { $header->setStatus('fa-square-o', 'bluegrey', pht('Open')); } else { $text = PonderQuestionStatus::getQuestionStatusFullName( $question->getStatus()); $icon = PonderQuestionStatus::getQuestionStatusIcon( $question->getStatus()); $header->setStatus($icon, 'dark', $text); } - $properties = $this->buildPropertyListView($question); - $actions = $this->buildActionListView($question); + $curtain = $this->buildCurtain($question); $details = $this->buildPropertySectionView($question); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $question, PhabricatorPolicyCapability::CAN_EDIT); $content_id = celerity_generate_unique_node_id(); $timeline = $this->buildTransactionTimeline( $question, id(new PonderQuestionTransactionQuery()) ->withTransactionTypes(array(PhabricatorTransactions::TYPE_COMMENT))); $xactions = $timeline->getTransactions(); $add_comment = id(new PhabricatorApplicationTransactionCommentView()) ->setUser($viewer) ->setObjectPHID($question->getPHID()) ->setShowPreview(false) ->setAction($this->getApplicationURI("/question/comment/{$id}/")) ->setSubmitButtonName(pht('Comment')); $add_comment = phutil_tag_div( 'ponder-question-add-comment-view', $add_comment); $comment_view = phutil_tag( 'div', array( 'id' => $content_id, 'style' => 'display: none;', ), array( $timeline, $add_comment, )); $footer = id(new PonderFooterView()) ->setContentID($content_id) ->setCount(count($xactions)); $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView()); $crumbs->addTextCrumb('Q'.$id, '/Q'.$id); $crumbs->setBorder(true); $subheader = $this->buildSubheaderView($question); $answer_wiki = null; if ($question->getAnswerWiki()) { $wiki = new PHUIRemarkupView($viewer, $question->getAnswerWiki()); $answer_wiki = id(new PHUIObjectBoxView()) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setHeaderText(pht('ANSWER SUMMARY')) ->appendChild($wiki) ->addClass('ponder-answer-wiki'); } require_celerity_resource('ponder-view-css'); $ponder_content = phutil_tag( 'div', array( 'class' => 'ponder-question-content', ), array( $answer_wiki, $footer, $comment_view, $answers, $answer_add_panel, )); $ponder_view = id(new PHUITwoColumnView()) ->setHeader($header) ->setSubheader($subheader) + ->setCurtain($curtain) ->setMainColumn($ponder_content) - ->setPropertyList($properties) ->addPropertySection(pht('DETAILS'), $details) - ->setActionList($actions) ->addClass('ponder-question-view'); $page_objects = array_merge( - array($question->getPHID()), - mpull($question->getAnswers(), 'getPHID')); + array($question->getPHID()), + mpull($question->getAnswers(), 'getPHID')); return $this->newPage() ->setTitle('Q'.$question->getID().' '.$question->getTitle()) ->setCrumbs($crumbs) ->setPageObjectPHIDs($page_objects) - ->appendChild( - array( - $ponder_view, - )); + ->appendChild($ponder_view); } - private function buildActionListView(PonderQuestion $question) { + private function buildCurtain(PonderQuestion $question) { $viewer = $this->getViewer(); - $request = $this->getRequest(); $id = $question->getID(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $question, PhabricatorPolicyCapability::CAN_EDIT); - $view = id(new PhabricatorActionListView()) - ->setUser($viewer) - ->setObject($question); + $curtain = $this->newCurtainView($question); if ($question->getStatus() == PonderQuestionStatus::STATUS_OPEN) { $name = pht('Close Question'); $icon = 'fa-check-square-o'; } else { $name = pht('Reopen Question'); $icon = 'fa-square-o'; } - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Edit Question')) ->setHref($this->getApplicationURI("/question/edit/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName($name) ->setIcon($icon) ->setWorkflow(true) ->setDisabled(!$can_edit) ->setHref($this->getApplicationURI("/question/status/{$id}/"))); - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-list') ->setName(pht('View History')) ->setHref($this->getApplicationURI("/question/history/{$id}/"))); - return $view; - } - - private function buildPropertyListView( - PonderQuestion $question) { - - $viewer = $this->getViewer(); - $view = id(new PHUIPropertyListView()) - ->setUser($viewer) - ->setObject($question); - - $view->invokeWillRenderEvent(); - - return $view; + return $curtain; } private function buildSubheaderView( PonderQuestion $question) { $viewer = $this->getViewer(); $asker = $viewer->renderHandle($question->getAuthorPHID())->render(); $date = phabricator_datetime($question->getDateCreated(), $viewer); $asker = phutil_tag('strong', array(), $asker); $author = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) ->withPHIDs(array($question->getAuthorPHID())) ->needProfileImage(true) ->executeOne(); $image_uri = $author->getProfileImageURI(); $image_href = '/p/'.$author->getUsername(); $content = pht('Asked by %s on %s.', $asker, $date); return id(new PHUIHeadThingView()) ->setImage($image_uri) ->setImageHref($image_href) ->setContent($content); } private function buildPropertySectionView( PonderQuestion $question) { $viewer = $this->getViewer(); $question_details = PhabricatorMarkupEngine::renderOneObject( $question, $question->getMarkupField(), $viewer); if (!$question_details) { $question_details = phutil_tag( 'em', array(), pht('No further details for this question.')); } $question_details = phutil_tag_div( 'phabricator-remarkup ml', $question_details); return $question_details; } /** * This is fairly non-standard; building N timelines at once (N = number of * answers) is tricky business. * * TODO - re-factor this to ajax in one answer panel at a time in a more * standard fashion. This is necessary to scale this application. */ private function buildAnswers(PonderQuestion $question) { $viewer = $this->getViewer(); $answers = $question->getAnswers(); if ($answers) { $author_phids = mpull($answers, 'getAuthorPHID'); $handles = $this->loadViewerHandles($author_phids); $view = array(); foreach ($answers as $answer) { $id = $answer->getID(); $handle = $handles[$answer->getAuthorPHID()]; $timeline = $this->buildTransactionTimeline( $answer, id(new PonderAnswerTransactionQuery()) ->withTransactionTypes(array(PhabricatorTransactions::TYPE_COMMENT))); $xactions = $timeline->getTransactions(); $view[] = id(new PonderAnswerView()) ->setUser($viewer) ->setAnswer($answer) ->setTransactions($xactions) ->setTimeline($timeline) ->setHandle($handle); } $header = id(new PHUIHeaderView()) ->setHeader('Answers'); return id(new PHUIBoxView()) ->addClass('ponder-answer-section') ->appendChild($header) ->appendChild($view); } return null; } } diff --git a/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php b/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php index 2eb2c08c75..f788f5e94c 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php @@ -1,177 +1,158 @@ getViewer(); $id = $request->getURIData('id'); $poll = id(new PhabricatorSlowvoteQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needOptions(true) ->needChoices(true) ->needViewerChoices(true) ->executeOne(); if (!$poll) { return new Aphront404Response(); } $poll_view = id(new SlowvoteEmbedView()) ->setUser($viewer) ->setPoll($poll); if ($request->isAjax()) { return id(new AphrontAjaxResponse()) ->setContent( array( 'pollID' => $poll->getID(), 'contentHTML' => $poll_view->render(), )); } $header_icon = $poll->getIsClosed() ? 'fa-ban' : 'fa-circle-o'; $header_name = $poll->getIsClosed() ? pht('Closed') : pht('Open'); $header_color = $poll->getIsClosed() ? 'dark' : 'bluegrey'; $header = id(new PHUIHeaderView()) ->setHeader($poll->getQuestion()) ->setUser($viewer) ->setStatus($header_icon, $header_color, $header_name) ->setPolicyObject($poll) ->setHeaderIcon('fa-bar-chart'); - $actions = $this->buildActionView($poll); - $properties = $this->buildPropertyView($poll); + $curtain = $this->buildCurtain($poll); $subheader = $this->buildSubheaderView($poll); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb('V'.$poll->getID()); $crumbs->setBorder(true); $timeline = $this->buildTransactionTimeline( $poll, new PhabricatorSlowvoteTransactionQuery()); $add_comment = $this->buildCommentForm($poll); $poll_content = array( $poll_view, $timeline, $add_comment, ); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setSubheader($subheader) - ->setMainColumn($poll_content) - ->setPropertyList($properties) - ->setActionList($actions); + ->setCurtain($curtain) + ->setMainColumn($poll_content); return $this->newPage() ->setTitle('V'.$poll->getID().' '.$poll->getQuestion()) ->setCrumbs($crumbs) ->setPageObjectPHIDs(array($poll->getPHID())) - ->appendChild( - array( - $view, - )); + ->appendChild($view); } - private function buildActionView(PhabricatorSlowvotePoll $poll) { - $viewer = $this->getRequest()->getUser(); - - $view = id(new PhabricatorActionListView()) - ->setUser($viewer) - ->setObject($poll); + private function buildCurtain(PhabricatorSlowvotePoll $poll) { + $viewer = $this->getViewer(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $poll, PhabricatorPolicyCapability::CAN_EDIT); + $curtain = $this->newCurtainView($poll); + $is_closed = $poll->getIsClosed(); $close_poll_text = $is_closed ? pht('Reopen Poll') : pht('Close Poll'); $close_poll_icon = $is_closed ? 'fa-play-circle-o' : 'fa-ban'; - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Poll')) ->setIcon('fa-pencil') ->setHref($this->getApplicationURI('edit/'.$poll->getID().'/')) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); - $view->addAction( + $curtain->addAction( id(new PhabricatorActionView()) ->setName($close_poll_text) ->setIcon($close_poll_icon) ->setHref($this->getApplicationURI('close/'.$poll->getID().'/')) ->setDisabled(!$can_edit) ->setWorkflow(true)); - return $view; - } - - private function buildPropertyView( - PhabricatorSlowvotePoll $poll) { - - $viewer = $this->getRequest()->getUser(); - $view = id(new PHUIPropertyListView()) - ->setUser($viewer) - ->setObject($poll); - $view->invokeWillRenderEvent(); - - return $view; + return $curtain; } private function buildSubheaderView( PhabricatorSlowvotePoll $poll) { $viewer = $this->getViewer(); $author = $viewer->renderHandle($poll->getAuthorPHID())->render(); $date = phabricator_datetime($poll->getDateCreated(), $viewer); $author = phutil_tag('strong', array(), $author); $person = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) ->withPHIDs(array($poll->getAuthorPHID())) ->needProfileImage(true) ->executeOne(); $image_uri = $person->getProfileImageURI(); $image_href = '/p/'.$person->getUsername(); $content = pht('Asked by %s on %s.', $author, $date); return id(new PHUIHeadThingView()) ->setImage($image_uri) ->setImageHref($image_href) ->setContent($content); } private function buildCommentForm(PhabricatorSlowvotePoll $poll) { $viewer = $this->getRequest()->getUser(); $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); $add_comment_header = $is_serious ? pht('Add Comment') : pht('Enter Deliberations'); $draft = PhabricatorDraft::newFromUserAndKey($viewer, $poll->getPHID()); return id(new PhabricatorApplicationTransactionCommentView()) ->setUser($viewer) ->setObjectPHID($poll->getPHID()) ->setDraft($draft) ->setHeaderText($add_comment_header) ->setAction($this->getApplicationURI('/comment/'.$poll->getID().'/')) ->setSubmitButtonName(pht('Add Comment')); } }