diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index 76c6cbaf27..71d4547559 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -1352,7 +1352,7 @@ celerity_register_resource_map(array( ), 'phabricator-feed-css' => array( - 'uri' => '/res/32e5879b/rsrc/css/application/feed/feed.css', + 'uri' => '/res/7d1d0015/rsrc/css/application/feed/feed.css', 'type' => 'css', 'requires' => array( @@ -1409,7 +1409,7 @@ celerity_register_resource_map(array( ), 'phabricator-profile-css' => array( - 'uri' => '/res/ebe1ac2f/rsrc/css/application/profile/profile-view.css', + 'uri' => '/res/9869d10b/rsrc/css/application/profile/profile-view.css', 'type' => 'css', 'requires' => array( diff --git a/src/applications/feed/builder/feed/PhabricatorFeedBuilder.php b/src/applications/feed/builder/feed/PhabricatorFeedBuilder.php index 3de6204571..147414f520 100644 --- a/src/applications/feed/builder/feed/PhabricatorFeedBuilder.php +++ b/src/applications/feed/builder/feed/PhabricatorFeedBuilder.php @@ -50,18 +50,44 @@ final class PhabricatorFeedBuilder { $null_view = new AphrontNullView(); - $views = array(); + require_celerity_resource('phabricator-feed-css'); + + $last_date = null; + $today = phabricator_date(time(), $user); foreach ($stories as $story) { $story->setHandles($handles); $story->setObjects($objects); + $date = phabricator_date($story->getEpoch(), $user); + if ($date == $today) { + $date = 'Today'; + } + + if ($date !== $last_date) { + if ($last_date !== null) { + $null_view->appendChild( + '
'); + } + $last_date = $date; + $null_view->appendChild( + phutil_render_tag( + 'div', + array( + 'class' => 'phabricator-feed-story-date', + ), + phutil_escape_html($date))); + } + $view = $story->renderView(); $view->setViewer($user); $null_view->appendChild($view); } - return $null_view; + return id(new AphrontNullView())->appendChild( + '
'. + $null_view->render(). + '
'); } } diff --git a/src/applications/feed/builder/feed/__init__.php b/src/applications/feed/builder/feed/__init__.php index 914e738afd..79b122f398 100644 --- a/src/applications/feed/builder/feed/__init__.php +++ b/src/applications/feed/builder/feed/__init__.php @@ -7,8 +7,11 @@ phutil_require_module('phabricator', 'applications/phid/handle/data'); +phutil_require_module('phabricator', 'infrastructure/celerity/api'); phutil_require_module('phabricator', 'view/null'); +phutil_require_module('phabricator', 'view/utils'); +phutil_require_module('phutil', 'markup'); phutil_require_module('phutil', 'utils'); diff --git a/src/applications/feed/story/base/PhabricatorFeedStory.php b/src/applications/feed/story/base/PhabricatorFeedStory.php index 313ddc1bad..a6828d16c5 100644 --- a/src/applications/feed/story/base/PhabricatorFeedStory.php +++ b/src/applications/feed/story/base/PhabricatorFeedStory.php @@ -59,4 +59,8 @@ abstract class PhabricatorFeedStory { return $this->data; } + final public function getEpoch() { + return $this->getStoryData()->getEpoch(); + } + } diff --git a/src/applications/feed/story/differential/PhabricatorFeedStoryDifferential.php b/src/applications/feed/story/differential/PhabricatorFeedStoryDifferential.php index 83395108ad..b4ab02028f 100644 --- a/src/applications/feed/story/differential/PhabricatorFeedStoryDifferential.php +++ b/src/applications/feed/story/differential/PhabricatorFeedStoryDifferential.php @@ -50,7 +50,7 @@ class PhabricatorFeedStoryDifferential extends PhabricatorFeedStory { $view->setTitle( ''.$handles[$author_phid]->renderLink().''. - ' '.$verb.' '. + ' '.$verb.' revision '. ''.$handles[$revision_phid]->renderLink().'.'); $view->setEpoch($data->getEpoch()); diff --git a/src/applications/feed/story/maniphest/PhabricatorFeedStoryManiphest.php b/src/applications/feed/story/maniphest/PhabricatorFeedStoryManiphest.php index ef27673a63..a5a45a52e4 100644 --- a/src/applications/feed/story/maniphest/PhabricatorFeedStoryManiphest.php +++ b/src/applications/feed/story/maniphest/PhabricatorFeedStoryManiphest.php @@ -49,7 +49,7 @@ class PhabricatorFeedStoryManiphest extends PhabricatorFeedStory { $verb = ManiphestAction::getActionPastTenseVerb($action); $title = ''.$handles[$author_phid]->renderLink().''. - " {$verb} ". + " {$verb} task ". ''.$handles[$task_phid]->renderLink().''; switch ($action) { case ManiphestAction::ACTION_ASSIGN: diff --git a/src/applications/project/controller/profile/PhabricatorProjectProfileController.php b/src/applications/project/controller/profile/PhabricatorProjectProfileController.php index fc86ffb693..52ecb766eb 100644 --- a/src/applications/project/controller/profile/PhabricatorProjectProfileController.php +++ b/src/applications/project/controller/profile/PhabricatorProjectProfileController.php @@ -82,14 +82,7 @@ class PhabricatorProjectProfileController )); $stories = $query->execute(); - $builder = new PhabricatorFeedBuilder($stories); - $builder->setUser($user); - $view = $builder->buildView(); - - $content .= - '
'. - $view->render(). - '
'; + $content .= $this->renderStories($stories); break; case 'about': $content = $this->renderAboutPage($project, $profile); @@ -104,7 +97,7 @@ class PhabricatorProjectProfileController throw new Exception("Unimplemented filter '{$this->page}'."); } - $content = '
'.$content.'
'; + $content = '
'.$content.'
'; $nav_view->appendChild($content); $header = new PhabricatorProfileHeaderView(); @@ -238,11 +231,22 @@ class PhabricatorProjectProfileController )); $stories = $query->execute(); + return $this->renderStories($stories); + } + + private function renderStories(array $stories) { + $builder = new PhabricatorFeedBuilder($stories); $builder->setUser($this->getRequest()->getUser()); $view = $builder->buildView(); - return $view->render(); + return + '
'. + '

Activity Feed

'. + '
'. + $view->render(). + '
'. + '
'; } diff --git a/webroot/rsrc/css/application/feed/feed.css b/webroot/rsrc/css/application/feed/feed.css index 089357f802..e9fae34971 100644 --- a/webroot/rsrc/css/application/feed/feed.css +++ b/webroot/rsrc/css/application/feed/feed.css @@ -2,6 +2,11 @@ * @provides phabricator-feed-css */ +.phabricator-feed-frame { + width: 640px; + padding: 1em; +} + .phabricator-feed-story { padding-left: 64px; margin: .5em 0 1em; @@ -27,3 +32,14 @@ color: #888888; font-size: 11px; } + +.phabricator-feed-story-date { + color: #666666; + font-size: 11px; + border-bottom: 1px solid #eeeeee; + padding: .5em 0; +} + +.phabricator-feed-story-date-separator { + margin-top: 2em; +} diff --git a/webroot/rsrc/css/application/profile/profile-view.css b/webroot/rsrc/css/application/profile/profile-view.css index 43c48395f2..9d348294cf 100644 --- a/webroot/rsrc/css/application/profile/profile-view.css +++ b/webroot/rsrc/css/application/profile/profile-view.css @@ -70,17 +70,16 @@ td.phabricator-profile-content { .phabricator-profile-info-group { margin-bottom: 2em; - background: #efefef; - border-top: 1px solid #cccccc; } .phabricator-profile-info-header { padding: 8px; - background: #dfdfdf; + background: #f0f0f0; + border-top: 1px solid #d9d9d9; } .phabricator-profile-info-pane { - padding: 8px 2em; + padding: 8px .5em; } .phabricator-profile-info-table {