diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -82,7 +82,7 @@ 'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b', 'rsrc/css/application/paste/paste.css' => 'b2f5a543', 'rsrc/css/application/people/people-profile.css' => '25970776', - 'rsrc/css/application/phame/phame.css' => 'bb147387', + 'rsrc/css/application/phame/phame.css' => 'd5528237', 'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee', 'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49', 'rsrc/css/application/pholio/pholio.css' => '95174bdd', @@ -127,6 +127,7 @@ 'rsrc/css/phui/phui-button.css' => '16020a60', 'rsrc/css/phui/phui-crumbs-view.css' => '414406b5', 'rsrc/css/phui/phui-document-pro.css' => 'e0fad431', + 'rsrc/css/phui/phui-document-summary.css' => 'bca1ed88', 'rsrc/css/phui/phui-document.css' => 'a4a1c3b9', 'rsrc/css/phui/phui-feed-story.css' => 'b7b26d23', 'rsrc/css/phui/phui-fontkit.css' => '9cda225e', @@ -771,7 +772,7 @@ 'phabricator-uiexample-reactor-sendclass' => '1def2711', 'phabricator-uiexample-reactor-sendproperties' => 'b1f0ccee', 'phabricator-zindex-css' => '57ddcaa2', - 'phame-css' => 'bb147387', + 'phame-css' => 'd5528237', 'pholio-css' => '95174bdd', 'pholio-edit-css' => '3ad9d1ee', 'pholio-inline-comments-css' => '8e545e49', @@ -789,6 +790,7 @@ 'phui-calendar-list-css' => 'c1c7f338', 'phui-calendar-month-css' => '476be7e0', 'phui-crumbs-view-css' => '414406b5', + 'phui-document-summary-view-css' => 'bca1ed88', 'phui-document-view-css' => 'a4a1c3b9', 'phui-document-view-pro-css' => 'e0fad431', 'phui-feed-story-css' => 'b7b26d23', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1441,6 +1441,7 @@ 'PHUIDiffTableOfContentsListView' => 'infrastructure/diff/view/PHUIDiffTableOfContentsListView.php', 'PHUIDiffTwoUpInlineCommentRowScaffold' => 'infrastructure/diff/view/PHUIDiffTwoUpInlineCommentRowScaffold.php', 'PHUIDocumentExample' => 'applications/uiexample/examples/PHUIDocumentExample.php', + 'PHUIDocumentSummaryView' => 'view/phui/PHUIDocumentSummaryView.php', 'PHUIDocumentView' => 'view/phui/PHUIDocumentView.php', 'PHUIDocumentViewPro' => 'view/phui/PHUIDocumentViewPro.php', 'PHUIFeedStoryExample' => 'applications/uiexample/examples/PHUIFeedStoryExample.php', @@ -3287,6 +3288,7 @@ 'PhameBlogFeedController' => 'applications/phame/controller/blog/PhameBlogFeedController.php', 'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php', 'PhameBlogLiveController' => 'applications/phame/controller/blog/PhameBlogLiveController.php', + 'PhameBlogManageController' => 'applications/phame/controller/blog/PhameBlogManageController.php', 'PhameBlogProfilePictureController' => 'applications/phame/controller/blog/PhameBlogProfilePictureController.php', 'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php', 'PhameBlogReplyHandler' => 'applications/phame/mail/PhameBlogReplyHandler.php', @@ -5424,6 +5426,7 @@ 'PHUIDiffTableOfContentsListView' => 'AphrontView', 'PHUIDiffTwoUpInlineCommentRowScaffold' => 'PHUIDiffInlineCommentRowScaffold', 'PHUIDocumentExample' => 'PhabricatorUIExample', + 'PHUIDocumentSummaryView' => 'AphrontTagView', 'PHUIDocumentView' => 'AphrontTagView', 'PHUIDocumentViewPro' => 'AphrontTagView', 'PHUIFeedStoryExample' => 'PhabricatorUIExample', @@ -7597,6 +7600,7 @@ 'PhameBlogFeedController' => 'PhameBlogController', 'PhameBlogListController' => 'PhameBlogController', 'PhameBlogLiveController' => 'PhameBlogController', + 'PhameBlogManageController' => 'PhameBlogController', 'PhameBlogProfilePictureController' => 'PhameBlogController', 'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhameBlogReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', diff --git a/src/applications/phame/application/PhabricatorPhameApplication.php b/src/applications/phame/application/PhabricatorPhameApplication.php --- a/src/applications/phame/application/PhabricatorPhameApplication.php +++ b/src/applications/phame/application/PhabricatorPhameApplication.php @@ -61,6 +61,7 @@ 'archive/(?P[^/]+)/' => 'PhameBlogArchiveController', 'edit/(?P[^/]+)/' => 'PhameBlogEditController', 'view/(?P[^/]+)/' => 'PhameBlogViewController', + 'manage/(?P[^/]+)/' => 'PhameBlogManageController', 'feed/(?P[^/]+)/' => 'PhameBlogFeedController', 'new/' => 'PhameBlogEditController', 'picture/(?P[1-9]\d*)/' => 'PhameBlogProfilePictureController', diff --git a/src/applications/phame/controller/PhameController.php b/src/applications/phame/controller/PhameController.php --- a/src/applications/phame/controller/PhameController.php +++ b/src/applications/phame/controller/PhameController.php @@ -2,113 +2,4 @@ abstract class PhameController extends PhabricatorController { - protected function renderPostList( - array $posts, - PhabricatorUser $viewer, - $nodata) { - assert_instances_of($posts, 'PhamePost'); - - $handle_phids = array(); - foreach ($posts as $post) { - $handle_phids[] = $post->getBloggerPHID(); - if ($post->getBlog()) { - $handle_phids[] = $post->getBlog()->getPHID(); - } - } - $handles = $viewer->loadHandles($handle_phids); - - $stories = array(); - foreach ($posts as $post) { - $blogger = $handles[$post->getBloggerPHID()]->renderLink(); - $blogger_uri = $handles[$post->getBloggerPHID()]->getURI(); - $blogger_image = $handles[$post->getBloggerPHID()]->getImageURI(); - - $blog = null; - if ($post->getBlog()) { - $blog = $handles[$post->getBlog()->getPHID()]->renderLink(); - } - - $phame_post = ''; - if ($post->getBody()) { - $phame_post = PhabricatorMarkupEngine::summarize($post->getBody()); - } - - $blog_view = $post->getViewURI(); - $phame_title = phutil_tag('a', array('href' => $blog_view), - $post->getTitle()); - - $blogger = phutil_tag('strong', array(), $blogger); - if ($post->isDraft()) { - $title = pht( - '%s drafted a blog post on %s.', - $blogger, - $blog); - $title = phutil_tag('em', array(), $title); - } else { - $title = pht( - '%s wrote a blog post on %s.', - $blogger, - $blog); - } - - $item = id(new PHUIObjectItemView()) - ->setObject($post) - ->setHeader($post->getTitle()) - ->setHref($this->getApplicationURI('post/view/'.$post->getID().'/')); - - $story = id(new PHUIFeedStoryView()) - ->setTitle($title) - ->setImage($blogger_image) - ->setImageHref($blogger_uri) - ->setAppIcon('fa-star') - ->setUser($viewer) - ->setPontification($phame_post, $phame_title); - - if (PhabricatorPolicyFilter::hasCapability( - $viewer, - $post, - PhabricatorPolicyCapability::CAN_EDIT)) { - - $story->addAction(id(new PHUIIconView()) - ->setHref($this->getApplicationURI('post/edit/'.$post->getID().'/')) - ->setIconFont('fa-pencil')); - } - - if ($post->getDatePublished()) { - $story->setEpoch($post->getDatePublished()); - } - - $stories[] = $story; - } - - if (empty($stories)) { - return id(new PHUIBoxView()) - ->appendChild($nodata) - ->addClass('mlt mlb msr msl'); - } - - return $stories; - } - - protected function buildApplicationCrumbs() { - $crumbs = parent::buildApplicationCrumbs(); - - $can_create = $this->hasApplicationCapability( - PhameBlogCreateCapability::CAPABILITY); - - $crumbs->addAction( - id(new PHUIListItemView()) - ->setName(pht('New Blog')) - ->setHref($this->getApplicationURI('/blog/new/')) - ->setIcon('fa-plus-square') - ->setDisabled(!$can_create) - ->setWorkflow(!$can_create)); - - $crumbs->addAction( - id(new PHUIListItemView()) - ->setName(pht('New Post')) - ->setHref($this->getApplicationURI('/post/new/')) - ->setIcon('fa-pencil')); - return $crumbs; - } } diff --git a/src/applications/phame/controller/blog/PhameBlogListController.php b/src/applications/phame/controller/blog/PhameBlogListController.php --- a/src/applications/phame/controller/blog/PhameBlogListController.php +++ b/src/applications/phame/controller/blog/PhameBlogListController.php @@ -31,4 +31,21 @@ return $nav; } + protected function buildApplicationCrumbs() { + $crumbs = parent::buildApplicationCrumbs(); + + $can_create = $this->hasApplicationCapability( + PhameBlogCreateCapability::CAPABILITY); + + $crumbs->addAction( + id(new PHUIListItemView()) + ->setName(pht('New Blog')) + ->setHref($this->getApplicationURI('/blog/new/')) + ->setIcon('fa-plus-square') + ->setDisabled(!$can_create) + ->setWorkflow(!$can_create)); + + return $crumbs; + } + } diff --git a/src/applications/phame/controller/blog/PhameBlogViewController.php b/src/applications/phame/controller/blog/PhameBlogManageController.php copy from src/applications/phame/controller/blog/PhameBlogViewController.php copy to src/applications/phame/controller/blog/PhameBlogManageController.php --- a/src/applications/phame/controller/blog/PhameBlogViewController.php +++ b/src/applications/phame/controller/blog/PhameBlogManageController.php @@ -1,6 +1,6 @@ getViewer(); @@ -15,14 +15,6 @@ return new Aphront404Response(); } - $pager = id(new AphrontCursorPagerView()) - ->readFromRequest($request); - - $posts = id(new PhamePostQuery()) - ->setViewer($viewer) - ->withBlogPHIDs(array($blog->getPHID())) - ->executeWithCursorPager($pager); - if ($blog->isArchived()) { $header_icon = 'fa-ban'; $header_name = pht('Archived'); @@ -44,14 +36,6 @@ $actions = $this->renderActions($blog, $viewer); $properties = $this->renderProperties($blog, $viewer, $actions); - $post_list = $this->renderPostList( - $posts, - $viewer, - pht('This blog has no visible posts.')); - - $post_list = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Latest Posts')) - ->appendChild($post_list); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb( @@ -64,13 +48,18 @@ ->setHeader($header) ->addPropertyList($properties); + $timeline = $this->buildTransactionTimeline( + $blog, + new PhameBlogTransactionQuery()); + $timeline->setShouldTerminate(true); + return $this->newPage() ->setTitle($blog->getName()) ->setCrumbs($crumbs) ->appendChild( array( $object_box, - $post_list, + $timeline, )); } diff --git a/src/applications/phame/controller/blog/PhameBlogViewController.php b/src/applications/phame/controller/blog/PhameBlogViewController.php --- a/src/applications/phame/controller/blog/PhameBlogViewController.php +++ b/src/applications/phame/controller/blog/PhameBlogViewController.php @@ -2,6 +2,8 @@ final class PhameBlogViewController extends PhameBlogController { + private $blog; + public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); $id = $request->getURIData('id'); @@ -14,6 +16,7 @@ if (!$blog) { return new Aphront404Response(); } + $this->blog = $blog; $pager = id(new AphrontCursorPagerView()) ->readFromRequest($request); @@ -33,110 +36,148 @@ $header_color = 'bluegrey'; } - $picture = $blog->getProfileImageURI(); + $actions = $this->renderActions($blog, $viewer); + $action_button = id(new PHUIButtonView()) + ->setTag('a') + ->setText(pht('Actions')) + ->setHref('#') + ->setIconFont('fa-bars') + ->addClass('phui-mobile-menu') + ->setDropdownMenu($actions); $header = id(new PHUIHeaderView()) ->setHeader($blog->getName()) ->setUser($viewer) ->setPolicyObject($blog) - ->setImage($picture) - ->setStatus($header_icon, $header_color, $header_name); + ->setStatus($header_icon, $header_color, $header_name) + ->addActionLink($action_button); - $actions = $this->renderActions($blog, $viewer); - $properties = $this->renderProperties($blog, $viewer, $actions); $post_list = $this->renderPostList( $posts, $viewer, pht('This blog has no visible posts.')); - $post_list = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Latest Posts')) - ->appendChild($post_list); - $crumbs = $this->buildApplicationCrumbs(); + $crumbs->setBorder(true); $crumbs->addTextCrumb( pht('Blogs'), $this->getApplicationURI('blog/')); $crumbs->addTextCrumb( $blog->getName()); - $object_box = id(new PHUIObjectBoxView()) + $page = id(new PHUIDocumentViewPro()) ->setHeader($header) - ->addPropertyList($properties); + ->appendChild($post_list); + + $description = $this->renderDescription($blog, $viewer); return $this->newPage() ->setTitle($blog->getName()) ->setCrumbs($crumbs) ->appendChild( array( - $object_box, - $post_list, + $page, + $description, )); } - private function renderProperties( + private function renderDescription( PhameBlog $blog, - PhabricatorUser $viewer, - PhabricatorActionListView $actions) { - - require_celerity_resource('aphront-tooltip-css'); - Javelin::initBehavior('phabricator-tooltips'); - - $properties = id(new PHUIPropertyListView()) - ->setUser($viewer) - ->setObject($blog) - ->setActionList($actions); - - $properties->addProperty( - pht('Skin'), - $blog->getSkin()); + PhabricatorUser $viewer) { - $properties->addProperty( - pht('Domain'), - $blog->getDomain()); - - $feed_uri = PhabricatorEnv::getProductionURI( - $this->getApplicationURI('blog/feed/'.$blog->getID().'/')); - $properties->addProperty( - pht('Atom URI'), - javelin_tag('a', - array( - 'href' => $feed_uri, - 'sigil' => 'has-tooltip', - 'meta' => array( - 'tip' => pht('Atom URI does not support custom domains.'), - 'size' => 320, - ), - ), - $feed_uri)); - - $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( - $viewer, - $blog); - - $properties->addProperty( - pht('Editable By'), - $descriptions[PhabricatorPolicyCapability::CAN_EDIT]); - - $engine = id(new PhabricatorMarkupEngine()) - ->setViewer($viewer) - ->addObject($blog, PhameBlog::MARKUP_FIELD_DESCRIPTION) - ->process(); - - $properties->invokeWillRenderEvent(); + require_celerity_resource('phame-css'); if (strlen($blog->getDescription())) { $description = PhabricatorMarkupEngine::renderOneObject( id(new PhabricatorMarkupOneOff())->setContent($blog->getDescription()), 'default', $viewer); - $properties->addSectionHeader( - pht('Description'), - PHUIPropertyListView::ICON_SUMMARY); - $properties->addTextContent($description); + } else { + $description = phutil_tag('em', array(), pht('No description.')); } - return $properties; + $picture = $blog->getProfileImageURI(); + $description = phutil_tag_div( + 'phame-blog-description-content', $description); + + $image = phutil_tag( + 'div', + array( + 'class' => 'phame-blog-description-image', + 'style' => 'background-image: url('.$picture.');', + )); + + $header = phutil_tag( + 'div', + array( + 'class' => 'phame-blog-description-name', + ), + pht('About %s', $blog->getName())); + + $view = phutil_tag( + 'div', + array( + 'class' => 'phame-blog-description', + ), + array( + $image, + $header, + $description, + )); + + return $view; + } + + protected function renderPostList( + array $posts, + PhabricatorUser $viewer, + $nodata) { + assert_instances_of($posts, 'PhamePost'); + + $handle_phids = array(); + foreach ($posts as $post) { + $handle_phids[] = $post->getBloggerPHID(); + if ($post->getBlog()) { + $handle_phids[] = $post->getBlog()->getPHID(); + } + } + $handles = $viewer->loadHandles($handle_phids); + + $list = array(); + foreach ($posts as $post) { + $blogger = $handles[$post->getBloggerPHID()]->renderLink(); + $blogger_uri = $handles[$post->getBloggerPHID()]->getURI(); + $blogger_image = $handles[$post->getBloggerPHID()]->getImageURI(); + + $phame_post = null; + if ($post->getBody()) { + $phame_post = PhabricatorMarkupEngine::summarize($post->getBody()); + $phame_post = new PHUIRemarkupView($viewer, $phame_post); + } else { + $phame_post = phutil_tag('em', array(), pht('Empty Post')); + } + + $blogger = phutil_tag('strong', array(), $blogger); + $date = phabricator_datetime($post->getDatePublished(), $viewer); + $subtitle = pht('Written by %s on %s.', $blogger, $date); + + $item = id(new PHUIDocumentSummaryView()) + ->setTitle($post->getTitle()) + ->setHref($this->getApplicationURI('/post/view/'.$post->getID().'/')) + ->setSubtitle($subtitle) + ->setImage($blogger_image) + ->setImageHref($blogger_uri) + ->setSummary($phame_post); + + $list[] = $item; + } + + if (empty($list)) { + $list = id(new PHUIInfoView()) + ->appendChild($nodata); + } + + return $list; } private function renderActions(PhameBlog $blog, PhabricatorUser $viewer) { @@ -168,39 +209,11 @@ $actions->addAction( id(new PhabricatorActionView()) ->setIcon('fa-pencil') - ->setHref($this->getApplicationURI('blog/edit/'.$blog->getID().'/')) - ->setName(pht('Edit Blog')) + ->setHref($this->getApplicationURI('blog/manage/'.$blog->getID().'/')) + ->setName(pht('Manage Blog')) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); - $actions->addAction( - id(new PhabricatorActionView()) - ->setIcon('fa-picture-o') - ->setHref($this->getApplicationURI('blog/picture/'.$blog->getID().'/')) - ->setName(pht('Edit Blog Picture')) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); - - if ($blog->isArchived()) { - $actions->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Activate Blog')) - ->setIcon('fa-check') - ->setHref( - $this->getApplicationURI('blog/archive/'.$blog->getID().'/')) - ->setDisabled(!$can_edit) - ->setWorkflow(true)); - } else { - $actions->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Archive Blog')) - ->setIcon('fa-ban') - ->setHref( - $this->getApplicationURI('blog/archive/'.$blog->getID().'/')) - ->setDisabled(!$can_edit) - ->setWorkflow(true)); - } - return $actions; } diff --git a/src/view/phui/PHUIDocumentSummaryView.php b/src/view/phui/PHUIDocumentSummaryView.php new file mode 100644 --- /dev/null +++ b/src/view/phui/PHUIDocumentSummaryView.php @@ -0,0 +1,86 @@ +title = $title; + return $this; + } + + public function setSubtitle($subtitle) { + $this->subtitle = $subtitle; + return $this; + } + + public function setImage($image) { + $this->image = $image; + return $this; + } + + public function setImageHref($image_href) { + $this->imageHref = $image_href; + return $this; + } + + public function setHref($href) { + $this->href = $href; + return $this; + } + + public function setSummary($summary) { + $this->summary = $summary; + return $this; + } + + protected function getTagAttributes() { + $classes = array(); + $classes[] = 'phui-document-summary-view'; + $classes[] = 'phabricator-remarkup'; + + return array( + 'class' => implode(' ', $classes), + ); + } + + protected function getTagContent() { + require_celerity_resource('phui-document-summary-view-css'); + + $title = phutil_tag( + 'a', + array( + 'href' => $this->href, + ), + $this->title); + + $header = phutil_tag( + 'h2', + array( + 'class' => 'remarkup-header', + ), + $title); + + $subtitle = phutil_tag( + 'div', + array( + 'class' => 'phui-document-summary-subtitle', + ), + $this->subtitle); + + $body = phutil_tag( + 'div', + array( + 'class' => 'phui-document-summary-body', + ), + $this->summary); + + return array($header, $subtitle, $body); + } + +} diff --git a/webroot/rsrc/css/application/phame/phame.css b/webroot/rsrc/css/application/phame/phame.css --- a/webroot/rsrc/css/application/phame/phame.css +++ b/webroot/rsrc/css/application/phame/phame.css @@ -2,8 +2,29 @@ * @provides phame-css */ -.fb-comments, -.fb-comments span, -.fb-comments iframe[style] { - width: 100% !important; +.phame-blog-description { + max-width: 800px; + margin: 32px auto; + position: relative; +} + +.phame-blog-description-name { + font-weight: bold; + font-size: {$biggerfontsize}; + margin: 0 0 4px 50px; +} + +.phame-blog-description-content { + margin-left: 50px; +} + +.phame-blog-description-image { + display: inline-block; + background-repeat: no-repeat; + background-size: 100%; + box-shadow: inset 0 0 0 1px rgba(55,55,55,.15); + width: 40px; + height: 40px; + border-radius: 3px; + position: absolute; } diff --git a/webroot/rsrc/css/phui/phui-document-summary.css b/webroot/rsrc/css/phui/phui-document-summary.css new file mode 100644 --- /dev/null +++ b/webroot/rsrc/css/phui/phui-document-summary.css @@ -0,0 +1,26 @@ +/** + * @provides phui-document-summary-view-css + */ + +.phui-document-summary-view { + +} + +body .phui-document-view .phui-document-summary-view h2.remarkup-header { + margin: 0; + padding: 0; +} + +.phui-document-summary-view h2.remarkup-header a { + color: {$darkbluetext}; +} + +.phui-document-summary-subtitle { + color: {$lightbluetext}; + font-size: {$normalfontsize}; + margin-bottom: 8px; +} + +.phui-document-summary-subtitle a { + color: {$darkbluetext}; +}