mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 00:42:41 +01:00
Rough cut of Project profile improvements
Summary: - Old page was useless and dumb. - New page looks a little less bad, functions a little less poorly. - Still lots of work to be done. Test Plan: - Viewed a project. - Clicked all the links on the left nav. - Here is a screenshot: https://secure.phabricator.com/file/view/PHID-FILE-4buzquotb3fo4dhlicrw/ Reviewers: btrahan, jungejason Reviewed By: jungejason CC: aran, jungejason Maniphest Tasks: T681 Differential Revision: 1246
This commit is contained in:
parent
540400a806
commit
43430e154d
10 changed files with 407 additions and 213 deletions
|
@ -211,6 +211,69 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/css/application/differential/add-comment.css',
|
||||
),
|
||||
'differential-revision-comment-css' =>
|
||||
array(
|
||||
'uri' => '/res/9fb8013b/rsrc/css/application/differential/revision-comment.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/differential/revision-comment.css',
|
||||
),
|
||||
'differential-revision-comment-list-css' =>
|
||||
array(
|
||||
'uri' => '/res/3b31faa3/rsrc/css/application/differential/revision-comment-list.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/differential/revision-comment-list.css',
|
||||
),
|
||||
'differential-revision-detail-css' =>
|
||||
array(
|
||||
'uri' => '/res/33592453/rsrc/css/application/differential/revision-detail.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/differential/revision-detail.css',
|
||||
),
|
||||
'differential-revision-history-css' =>
|
||||
array(
|
||||
'uri' => '/res/0d7d515d/rsrc/css/application/differential/revision-history.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/differential/revision-history.css',
|
||||
),
|
||||
'differential-table-of-contents-css' =>
|
||||
array(
|
||||
'uri' => '/res/d173445b/rsrc/css/application/differential/table-of-contents.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/differential/table-of-contents.css',
|
||||
),
|
||||
'diffusion-commit-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/bc39d876/rsrc/css/application/diffusion/commit-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/diffusion/commit-view.css',
|
||||
),
|
||||
'diffusion-source-css' =>
|
||||
array(
|
||||
'uri' => '/res/db4566b6/rsrc/css/application/diffusion/diffusion-source.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/diffusion/diffusion-source.css',
|
||||
),
|
||||
'files-css' =>
|
||||
array(
|
||||
'uri' => '/res/a265a77d/rsrc/css/application/files/files.css',
|
||||
|
@ -229,6 +292,25 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/css/application/herald/herald.css',
|
||||
),
|
||||
'herald-rule-editor' =>
|
||||
array(
|
||||
'uri' => '/res/4d6dff2b/rsrc/js/application/herald/HeraldRuleEditor.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'multirow-row-manager',
|
||||
1 => 'javelin-install',
|
||||
2 => 'javelin-typeahead',
|
||||
3 => 'javelin-util',
|
||||
4 => 'javelin-dom',
|
||||
5 => 'javelin-tokenizer',
|
||||
6 => 'javelin-typeahead-preloaded-source',
|
||||
7 => 'javelin-stratcom',
|
||||
8 => 'javelin-json',
|
||||
9 => 'phabricator-prefab',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/herald/HeraldRuleEditor.js',
|
||||
),
|
||||
'herald-test-css' =>
|
||||
array(
|
||||
'uri' => '/res/c0cd6bdb/rsrc/css/application/herald/herald-test.css',
|
||||
|
@ -248,6 +330,17 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/javelin/lib/behavior.js',
|
||||
),
|
||||
0 =>
|
||||
array(
|
||||
'uri' => '/res/b6096fdd/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-uri',
|
||||
1 => 'javelin-php-serializer',
|
||||
),
|
||||
'disk' => '/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||
),
|
||||
'javelin-behavior-aphront-basic-tokenizer' =>
|
||||
array(
|
||||
'uri' => '/res/9be30797/rsrc/js/application/core/behavior-tokenizer.js',
|
||||
|
@ -313,99 +406,6 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/countdown/timer.js',
|
||||
),
|
||||
0 =>
|
||||
array(
|
||||
'uri' => '/res/b6096fdd/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-uri',
|
||||
1 => 'javelin-php-serializer',
|
||||
),
|
||||
'disk' => '/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||
),
|
||||
'differential-revision-comment-css' =>
|
||||
array(
|
||||
'uri' => '/res/9fb8013b/rsrc/css/application/differential/revision-comment.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/differential/revision-comment.css',
|
||||
),
|
||||
'differential-revision-comment-list-css' =>
|
||||
array(
|
||||
'uri' => '/res/3b31faa3/rsrc/css/application/differential/revision-comment-list.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/differential/revision-comment-list.css',
|
||||
),
|
||||
'differential-revision-detail-css' =>
|
||||
array(
|
||||
'uri' => '/res/33592453/rsrc/css/application/differential/revision-detail.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/differential/revision-detail.css',
|
||||
),
|
||||
'differential-revision-history-css' =>
|
||||
array(
|
||||
'uri' => '/res/0d7d515d/rsrc/css/application/differential/revision-history.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/differential/revision-history.css',
|
||||
),
|
||||
'differential-table-of-contents-css' =>
|
||||
array(
|
||||
'uri' => '/res/d173445b/rsrc/css/application/differential/table-of-contents.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/differential/table-of-contents.css',
|
||||
),
|
||||
'diffusion-commit-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/bc39d876/rsrc/css/application/diffusion/commit-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/diffusion/commit-view.css',
|
||||
),
|
||||
'diffusion-source-css' =>
|
||||
array(
|
||||
'uri' => '/res/db4566b6/rsrc/css/application/diffusion/diffusion-source.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/diffusion/diffusion-source.css',
|
||||
),
|
||||
'herald-rule-editor' =>
|
||||
array(
|
||||
'uri' => '/res/4d6dff2b/rsrc/js/application/herald/HeraldRuleEditor.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'multirow-row-manager',
|
||||
1 => 'javelin-install',
|
||||
2 => 'javelin-typeahead',
|
||||
3 => 'javelin-util',
|
||||
4 => 'javelin-dom',
|
||||
5 => 'javelin-tokenizer',
|
||||
6 => 'javelin-typeahead-preloaded-source',
|
||||
7 => 'javelin-stratcom',
|
||||
8 => 'javelin-json',
|
||||
9 => 'phabricator-prefab',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/herald/HeraldRuleEditor.js',
|
||||
),
|
||||
'javelin-behavior-dark-console' =>
|
||||
array(
|
||||
'uri' => '/res/c80156c4/rsrc/js/application/core/behavior-dark-console.js',
|
||||
|
@ -1416,6 +1416,15 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/css/application/profile/profile-view.css',
|
||||
),
|
||||
'phabricator-profile-header-css' =>
|
||||
array(
|
||||
'uri' => '/res/d39ef6a4/rsrc/css/application/profile/profile-header-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/profile/profile-header-view.css',
|
||||
),
|
||||
'phabricator-remarkup-css' =>
|
||||
array(
|
||||
'uri' => '/res/78f26382/rsrc/css/core/remarkup.css',
|
||||
|
|
|
@ -567,6 +567,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleListController' => 'applications/people/controller/list',
|
||||
'PhabricatorPeopleLogsController' => 'applications/people/controller/logs',
|
||||
'PhabricatorPeopleProfileController' => 'applications/people/controller/profile',
|
||||
'PhabricatorProfileHeaderView' => 'view/layout/profileheader',
|
||||
'PhabricatorProfileView' => 'view/layout/profile',
|
||||
'PhabricatorProject' => 'applications/project/storage/project',
|
||||
'PhabricatorProjectAffiliation' => 'applications/project/storage/affiliation',
|
||||
|
@ -1214,6 +1215,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleListController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorProfileHeaderView' => 'AphrontView',
|
||||
'PhabricatorProfileView' => 'AphrontView',
|
||||
'PhabricatorProject' => 'PhabricatorProjectDAO',
|
||||
'PhabricatorProjectAffiliation' => 'PhabricatorProjectDAO',
|
||||
|
|
|
@ -89,13 +89,18 @@ final class PhabricatorImageTransformer {
|
|||
$scale = min($x / $dx, $y / $dy);
|
||||
$dst = imagecreatetruecolor($dx, $dy);
|
||||
|
||||
// If we need to chop off some pixels, chop them off from the sides instead
|
||||
// of scaling in on <0, 0>.
|
||||
$sdx = $scale * $dx;
|
||||
$sdy = $scale * $dy;
|
||||
|
||||
imagecopyresampled(
|
||||
$dst,
|
||||
$src,
|
||||
0, 0,
|
||||
0, 0,
|
||||
($x - $sdx) / 2, ($y - $sdy) / 2,
|
||||
$dx, $dy,
|
||||
$scale * $dx, $scale * $dy);
|
||||
$sdx, $sdy);
|
||||
|
||||
return $dst;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ class PhabricatorProjectProfileController
|
|||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
$uri = $request->getRequestURI();
|
||||
|
||||
$project = id(new PhabricatorProject())->load($this->id);
|
||||
if (!$project) {
|
||||
|
@ -47,128 +46,111 @@ class PhabricatorProjectProfileController
|
|||
}
|
||||
$picture = PhabricatorFileURI::getViewURIForPHID($src_phid);
|
||||
|
||||
$pages = array(
|
||||
/*
|
||||
'<h2>Active Documents</h2>',
|
||||
'tasks' => 'Maniphest Tasks',
|
||||
'revisions' => 'Differential Revisions',
|
||||
'<hr />',
|
||||
'<h2>Workflow</h2>',
|
||||
'goals' => 'Goals',
|
||||
'statistics' => 'Statistics',
|
||||
'<hr />', */
|
||||
'<h2>Information</h2>',
|
||||
'edit' => 'Edit Project',
|
||||
'affiliation' => 'Edit Affiliation',
|
||||
);
|
||||
$nav_view = new AphrontSideNavFilterView();
|
||||
$uri = new PhutilURI('/project/view/'.$project->getID().'/');
|
||||
$nav_view->setBaseURI($uri);
|
||||
|
||||
if (empty($pages[$this->page])) {
|
||||
$this->page = 'action';
|
||||
}
|
||||
$external_arrow = "\xE2\x86\x97";
|
||||
$tasks_uri = '/maniphest/view/all/?projects='.$project->getPHID();
|
||||
$slug = PhrictionDocument::normalizeSlug($project->getName());
|
||||
$phriction_uri = '/w/projects/'.$slug.'/';
|
||||
|
||||
$edit_uri = '/project/edit/'.$project->getID().'/';
|
||||
|
||||
$nav_view->addFilter('dashboard', 'Dashboard');
|
||||
$nav_view->addSpacer();
|
||||
$nav_view->addFilter('feed', 'Feed');
|
||||
$nav_view->addFilter(null, 'Tasks '.$external_arrow, $tasks_uri);
|
||||
$nav_view->addFilter(null, 'Wiki '.$external_arrow, $phriction_uri);
|
||||
$nav_view->addFilter('people', 'People');
|
||||
$nav_view->addFilter('about', 'About');
|
||||
$nav_view->addSpacer();
|
||||
$nav_view->addFilter(null, "Edit Project\xE2\x80\xA6", $edit_uri);
|
||||
|
||||
$this->page = $nav_view->selectFilter($this->page, 'dashboard');
|
||||
|
||||
|
||||
require_celerity_resource('phabricator-profile-css');
|
||||
switch ($this->page) {
|
||||
default:
|
||||
$content = $this->renderBasicInformation($project, $profile);
|
||||
case 'dashboard':
|
||||
$content = $this->renderTasksPage($project, $profile);
|
||||
|
||||
$query = new PhabricatorFeedQuery();
|
||||
$query->setFilterPHIDs(
|
||||
array(
|
||||
$project->getPHID(),
|
||||
));
|
||||
$stories = $query->execute();
|
||||
|
||||
$builder = new PhabricatorFeedBuilder($stories);
|
||||
$builder->setUser($user);
|
||||
$view = $builder->buildView();
|
||||
|
||||
$content .=
|
||||
'<div style="padding: 2em;">'.
|
||||
$view->render().
|
||||
'</div>';
|
||||
break;
|
||||
case 'about':
|
||||
$content = $this->renderAboutPage($project, $profile);
|
||||
break;
|
||||
case 'people':
|
||||
$content = $this->renderPeoplePage($project, $profile);
|
||||
break;
|
||||
case 'feed':
|
||||
$content = $this->renderFeedPage($project, $profile);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unimplemented filter '{$this->page}'.");
|
||||
}
|
||||
|
||||
$profile = new PhabricatorProfileView();
|
||||
$profile->setProfilePicture($picture);
|
||||
$profile->setProfileNames($project->getName());
|
||||
foreach ($pages as $page => $name) {
|
||||
if (is_integer($page)) {
|
||||
$profile->addProfileItem(
|
||||
phutil_render_tag(
|
||||
'span',
|
||||
array(),
|
||||
$name));
|
||||
} else {
|
||||
$uri->setPath('/project/'.$page.'/'.$project->getID().'/');
|
||||
$profile->addProfileItem(
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $uri,
|
||||
'class' => ($this->page == $page)
|
||||
? 'phabricator-profile-item-selected'
|
||||
: null,
|
||||
),
|
||||
phutil_escape_html($name)));
|
||||
}
|
||||
}
|
||||
$content = '<div style="padding: 2em;">'.$content.'</div>';
|
||||
$nav_view->appendChild($content);
|
||||
|
||||
$profile->appendChild($content);
|
||||
$header = new PhabricatorProfileHeaderView();
|
||||
$header->setName($project->getName());
|
||||
$header->setDescription(
|
||||
phutil_utf8_shorten($profile->getBlurb(), 1024));
|
||||
$header->setProfilePicture($picture);
|
||||
|
||||
$header->appendChild($nav_view);
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$profile,
|
||||
$header,
|
||||
array(
|
||||
'title' => $project->getName(),
|
||||
));
|
||||
'title' => $project->getName().' Project',
|
||||
));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Helper functions
|
||||
private function renderAboutPage(
|
||||
PhabricatorProject $project,
|
||||
PhabricatorProjectProfile $profile) {
|
||||
|
||||
private function renderBasicInformation($project, $profile) {
|
||||
$blurb = nonempty(
|
||||
$profile->getBlurb(),
|
||||
'//Nothing is known about this elusive project.//');
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
|
||||
$engine = PhabricatorMarkupEngine::newProfileMarkupEngine();
|
||||
$blurb = $engine->markupText($blurb);
|
||||
|
||||
$affiliations = $project->loadAffiliations();
|
||||
$blurb = $profile->getBlurb();
|
||||
$blurb = phutil_escape_html($blurb);
|
||||
$blurb = str_replace("\n", '<br />', $blurb);
|
||||
|
||||
$phids = array_merge(
|
||||
array($project->getAuthorPHID()),
|
||||
$project->getSubprojectPHIDs(),
|
||||
mpull($affiliations, 'getUserPHID')
|
||||
$project->getSubprojectPHIDs()
|
||||
);
|
||||
$phids = array_unique($phids);
|
||||
$handles = id(new PhabricatorObjectHandleData($phids))
|
||||
->loadHandles();
|
||||
|
||||
$affiliated = array();
|
||||
foreach ($affiliations as $affiliation) {
|
||||
$user = $handles[$affiliation->getUserPHID()]->renderLink();
|
||||
$role = phutil_escape_html($affiliation->getRole());
|
||||
$affiliated[] = '<li>'.$user.' — '.$role.'</li>';
|
||||
}
|
||||
|
||||
if ($affiliated) {
|
||||
$affiliated = '<ul>'.implode("\n", $affiliated).'</ul>';
|
||||
} else {
|
||||
$affiliated = '<p><em>No one is affiliated with this project.</em></p>';
|
||||
}
|
||||
|
||||
if ($project->getSubprojectPHIDs()) {
|
||||
$table = $this->renderSubprojectTable(
|
||||
$handles,
|
||||
$project->getSubprojectPHIDs());
|
||||
$subproject_list = $table->render();
|
||||
} else {
|
||||
$subproject_list =
|
||||
'<p><em>There are no projects attached for such specie.</em></p>';
|
||||
}
|
||||
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
$timestamp = phabricator_datetime($project->getDateCreated(), $viewer);
|
||||
$status = PhabricatorProjectStatus::getNameForStatus(
|
||||
$project->getStatus());
|
||||
|
||||
$content =
|
||||
$about =
|
||||
'<div class="phabricator-profile-info-group">
|
||||
<h1 class="phabricator-profile-info-header">Basic Information</h1>
|
||||
<h1 class="phabricator-profile-info-header">About</h1>
|
||||
<div class="phabricator-profile-info-pane">
|
||||
<table class="phabricator-profile-info-table">
|
||||
<tr>
|
||||
<th>Creator</th>
|
||||
<td>'.$handles[$project->getAuthorPHID()]->renderLink().'</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<td><strong>'.phutil_escape_html($status).'</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Created</th>
|
||||
<td>'.$timestamp.'</td>
|
||||
|
@ -185,20 +167,88 @@ class PhabricatorProjectProfileController
|
|||
</div>
|
||||
</div>';
|
||||
|
||||
$content .=
|
||||
if ($project->getSubprojectPHIDs()) {
|
||||
$table = $this->renderSubprojectTable(
|
||||
$handles,
|
||||
$project->getSubprojectPHIDs());
|
||||
$subproject_list = $table->render();
|
||||
} else {
|
||||
$subproject_list = '<p><em>No subprojects.</em></p>';
|
||||
}
|
||||
|
||||
$about .=
|
||||
'<div class="phabricator-profile-info-group">'.
|
||||
'<h1 class="phabricator-profile-info-header">Resources</h1>'.
|
||||
'<h1 class="phabricator-profile-info-header">Subprojects</h1>'.
|
||||
'<div class="phabricator-profile-info-pane">'.
|
||||
$subproject_list.
|
||||
'</div>'.
|
||||
'</div>';
|
||||
|
||||
return $about;
|
||||
}
|
||||
|
||||
private function renderPeoplePage(
|
||||
PhabricatorProject $project,
|
||||
PhabricatorProjectProfile $profile) {
|
||||
|
||||
$affiliations = $project->loadAffiliations();
|
||||
|
||||
$phids = mpull($affiliations, 'getUserPHID');
|
||||
$handles = id(new PhabricatorObjectHandleData($phids))
|
||||
->loadHandles();
|
||||
|
||||
$affiliated = array();
|
||||
foreach ($affiliations as $affiliation) {
|
||||
$user = $handles[$affiliation->getUserPHID()]->renderLink();
|
||||
$role = phutil_escape_html($affiliation->getRole());
|
||||
$affiliated[] = '<li>'.$user.' — '.$role.'</li>';
|
||||
}
|
||||
|
||||
if ($affiliated) {
|
||||
$affiliated = '<ul>'.implode("\n", $affiliated).'</ul>';
|
||||
} else {
|
||||
$affiliated = '<p><em>No one is affiliated with this project.</em></p>';
|
||||
}
|
||||
|
||||
return
|
||||
'<div class="phabricator-profile-info-group">'.
|
||||
'<h1 class="phabricator-profile-info-header">People</h1>'.
|
||||
'<div class="phabricator-profile-info-pane">'.
|
||||
$affiliated.
|
||||
'</div>'.
|
||||
'</div>';
|
||||
}
|
||||
|
||||
$content .= '<div class="phabricator-profile-info-group">'.
|
||||
'<h1 class="phabricator-profile-info-header">Subprojects</h1>'.
|
||||
'<div class="phabricator-profile-info-pane">'.
|
||||
$subproject_list.
|
||||
'</div>'.
|
||||
'</div>';
|
||||
private function renderFeedPage(
|
||||
PhabricatorProject $project,
|
||||
PhabricatorProjectProfile $profile) {
|
||||
|
||||
$query = new PhabricatorFeedQuery();
|
||||
$query->setFilterPHIDs(array($project->getPHID()));
|
||||
$stories = $query->execute();
|
||||
|
||||
if (!$stories) {
|
||||
return 'There are no stories about this project.';
|
||||
}
|
||||
|
||||
$query = new PhabricatorFeedQuery();
|
||||
$query->setFilterPHIDs(
|
||||
array(
|
||||
$project->getPHID(),
|
||||
));
|
||||
$stories = $query->execute();
|
||||
|
||||
$builder = new PhabricatorFeedBuilder($stories);
|
||||
$builder->setUser($this->getRequest()->getUser());
|
||||
$view = $builder->buildView();
|
||||
|
||||
return $view->render();
|
||||
}
|
||||
|
||||
|
||||
private function renderTasksPage(
|
||||
PhabricatorProject $project,
|
||||
PhabricatorProjectProfile $profile) {
|
||||
|
||||
$query = id(new ManiphestTaskQuery())
|
||||
->withProjects(array($project->getPHID()))
|
||||
|
@ -238,7 +288,7 @@ class PhabricatorProjectProfileController
|
|||
),
|
||||
"View All Open Tasks \xC2\xBB");
|
||||
|
||||
$content .=
|
||||
$content =
|
||||
'<div class="phabricator-profile-info-group">
|
||||
<h1 class="phabricator-profile-info-header">'.
|
||||
"Open Tasks ({$open})".
|
||||
|
|
|
@ -7,20 +7,24 @@
|
|||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/404');
|
||||
phutil_require_module('phabricator', 'applications/feed/builder/feed');
|
||||
phutil_require_module('phabricator', 'applications/feed/query');
|
||||
phutil_require_module('phabricator', 'applications/files/uri');
|
||||
phutil_require_module('phabricator', 'applications/maniphest/query');
|
||||
phutil_require_module('phabricator', 'applications/maniphest/view/tasksummary');
|
||||
phutil_require_module('phabricator', 'applications/markup/engine');
|
||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||
phutil_require_module('phabricator', 'applications/project/constants/status');
|
||||
phutil_require_module('phabricator', 'applications/phriction/storage/document');
|
||||
phutil_require_module('phabricator', 'applications/project/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/project/storage/profile');
|
||||
phutil_require_module('phabricator', 'applications/project/storage/project');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
phutil_require_module('phabricator', 'view/layout/profile');
|
||||
phutil_require_module('phabricator', 'view/layout/profileheader');
|
||||
phutil_require_module('phabricator', 'view/layout/sidenavfilter');
|
||||
phutil_require_module('phabricator', 'view/utils');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'parser/uri');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
|
|
|
@ -89,11 +89,10 @@ class PhabricatorProjectProfileEditController
|
|||
$okay = $file->isTransformableImage();
|
||||
if ($okay) {
|
||||
$xformer = new PhabricatorImageTransformer();
|
||||
$xformed = $xformer->executeProfileTransform(
|
||||
$xformed = $xformer->executeThumbTransform(
|
||||
$file,
|
||||
$width = 280,
|
||||
$min_height = 140,
|
||||
$max_height = 420);
|
||||
$x = 50,
|
||||
$y = 50);
|
||||
$profile->setProfileImagePHID($xformed->getPHID());
|
||||
} else {
|
||||
$errors[] =
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorProfileHeaderView extends AphrontView {
|
||||
|
||||
protected $profilePicture;
|
||||
protected $profileName;
|
||||
protected $profileDescription;
|
||||
|
||||
public function setProfilePicture($picture) {
|
||||
$this->profilePicture = $picture;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setName($name) {
|
||||
$this->profileName = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDescription($description) {
|
||||
$this->profileDescription = $description;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
require_celerity_resource('phabricator-profile-header-css');
|
||||
|
||||
$image = null;
|
||||
if ($this->profilePicture) {
|
||||
$image = phutil_render_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'profile-header-picture-frame',
|
||||
'style' => 'background-image: url('.$this->profilePicture.');',
|
||||
),
|
||||
'');
|
||||
}
|
||||
|
||||
return
|
||||
'<table class="phabricator-profile-header">
|
||||
<tr>
|
||||
<td class="profile-header-name">'.
|
||||
phutil_escape_html($this->profileName).
|
||||
'</td>
|
||||
<td class="profile-header-picture" rowspan="2">'.
|
||||
$image.
|
||||
'</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="profile-header-description">'.
|
||||
phutil_escape_html($this->profileDescription).
|
||||
'</td>
|
||||
</tr>
|
||||
</table>'.
|
||||
$this->renderChildren();
|
||||
}
|
||||
}
|
15
src/view/layout/profileheader/__init__.php
Normal file
15
src/view/layout/profileheader/__init__.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorProfileHeaderView.php');
|
|
@ -41,8 +41,8 @@ final class AphrontSideNavFilterView extends AphrontView {
|
|||
private $baseURI;
|
||||
private $selectedFilter = false;
|
||||
|
||||
public function addFilter($key, $name) {
|
||||
$this->items[] = array('filter', $key, $name);
|
||||
public function addFilter($key, $name, $uri = null) {
|
||||
$this->items[] = array('filter', $key, $name, 'uri' => $uri);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -63,11 +63,13 @@ final class AphrontSideNavFilterView extends AphrontView {
|
|||
|
||||
public function selectFilter($key, $default) {
|
||||
$this->selectedFilter = $default;
|
||||
foreach ($this->items as $item) {
|
||||
if ($item[0] == 'filter') {
|
||||
if ($item[1] == $key) {
|
||||
$this->selectedFilter = $key;
|
||||
break;
|
||||
if ($key !== null) {
|
||||
foreach ($this->items as $item) {
|
||||
if ($item[0] == 'filter') {
|
||||
if ($item[1] == $key) {
|
||||
$this->selectedFilter = $key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,9 +103,13 @@ final class AphrontSideNavFilterView extends AphrontView {
|
|||
? 'aphront-side-nav-selected'
|
||||
: null;
|
||||
|
||||
$href = clone $this->baseURI;
|
||||
$href->setPath($href->getPath().$key.'/');
|
||||
$href = (string)$href;
|
||||
if (empty($item['uri'])) {
|
||||
$href = clone $this->baseURI;
|
||||
$href->setPath($href->getPath().$key.'/');
|
||||
$href = (string)$href;
|
||||
} else {
|
||||
$href = $item['uri'];
|
||||
}
|
||||
|
||||
$view->addNavItem(
|
||||
phutil_render_tag(
|
||||
|
|
32
webroot/rsrc/css/application/profile/profile-header-view.css
Normal file
32
webroot/rsrc/css/application/profile/profile-header-view.css
Normal file
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* @provides phabricator-profile-header-css
|
||||
*/
|
||||
|
||||
.phabricator-profile-header {
|
||||
background: #efefef;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #cccccc;
|
||||
}
|
||||
|
||||
.phabricator-profile-header .profile-header-name {
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
padding: 12px 12px 6px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.phabricator-profile-header .profile-header-picture-frame {
|
||||
margin: 11px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
position: relative;
|
||||
|
||||
background: no-repeat;
|
||||
border: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
.phabricator-profile-header .profile-header-description {
|
||||
padding: 0 12px 12px;
|
||||
color: #444444;
|
||||
font-size: 11px;
|
||||
}
|
Loading…
Reference in a new issue