1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-30 10:42:41 +01:00

Moderize Projects

Summary: Add mobile menus, PHTs and clean up panels. There is a litle more to do, but will tackle feed, etc in another diff.

Test Plan: Test Project filters on Chrome and iOS browser.

Reviewers: epriestley, btrahan

Reviewed By: epriestley

CC: aran, Korvin

Differential Revision: https://secure.phabricator.com/D4931
This commit is contained in:
Chad Little 2013-02-13 09:22:14 -08:00
parent 829fa6664f
commit b4d69800f9
9 changed files with 182 additions and 92 deletions

View file

@ -3,11 +3,11 @@
final class PhabricatorApplicationProject extends PhabricatorApplication { final class PhabricatorApplicationProject extends PhabricatorApplication {
public function getName() { public function getName() {
return 'Projects'; return pht('Projects');
} }
public function getShortDescription() { public function getShortDescription() {
return 'Organize Work'; return pht('Organize Work');
} }
public function getBaseURI() { public function getBaseURI() {

View file

@ -5,7 +5,7 @@ abstract class PhabricatorProjectController extends PhabricatorController {
public function buildStandardPageResponse($view, array $data) { public function buildStandardPageResponse($view, array $data) {
$page = $this->buildStandardPageView(); $page = $this->buildStandardPageView();
$page->setApplicationName('Project'); $page->setApplicationName(pht('Project'));
$page->setBaseURI('/project/'); $page->setBaseURI('/project/');
$page->setTitle(idx($data, 'title')); $page->setTitle(idx($data, 'title'));
$page->setGlyph("\xE2\x98\xA3"); $page->setGlyph("\xE2\x98\xA3");
@ -30,29 +30,29 @@ abstract class PhabricatorProjectController extends PhabricatorController {
$edit_uri = '/project/edit/'.$id.'/'; $edit_uri = '/project/edit/'.$id.'/';
$members_uri = '/project/members/'.$id.'/'; $members_uri = '/project/members/'.$id.'/';
$nav_view->addFilter('dashboard', 'Dashboard'); $nav_view->addFilter('dashboard', pht('Dashboard'));
$nav_view->addFilter('feed', 'Feed'); $nav_view->addFilter('feed', pht('Feed'));
$nav_view->addFilter(null, 'Tasks '.$external_arrow, $tasks_uri); $nav_view->addFilter(null, pht('Tasks').' '.$external_arrow, $tasks_uri);
$nav_view->addFilter(null, 'Wiki '.$external_arrow, $phriction_uri); $nav_view->addFilter(null, pht('Wiki').' '.$external_arrow, $phriction_uri);
$nav_view->addFilter('people', 'People'); $nav_view->addFilter('people', pht('People'));
$nav_view->addFilter('about', 'About'); $nav_view->addFilter('about', pht('About'));
$user = $this->getRequest()->getUser(); $user = $this->getRequest()->getUser();
$can_edit = PhabricatorPolicyCapability::CAN_EDIT; $can_edit = PhabricatorPolicyCapability::CAN_EDIT;
if (PhabricatorPolicyFilter::hasCapability($user, $project, $can_edit)) { if (PhabricatorPolicyFilter::hasCapability($user, $project, $can_edit)) {
$nav_view->addFilter('edit', "Edit Project\xE2\x80\xA6", $edit_uri); $nav_view->addFilter('edit', pht("Edit Project"), $edit_uri);
$nav_view->addFilter('members', "Edit Members\xE2\x80\xA6", $members_uri); $nav_view->addFilter('members', pht("Edit Members"), $members_uri);
} else { } else {
$nav_view->addFilter( $nav_view->addFilter(
'edit', 'edit',
"Edit Project\xE2\x80\xA6", pht("Edit Project"),
$edit_uri, $edit_uri,
$relative = false, $relative = false,
'disabled'); 'disabled');
$nav_view->addFilter( $nav_view->addFilter(
'members', 'members',
"Edit Members\xE2\x80\xA6", pht("Edit Members"),
$members_uri, $members_uri,
$relative = false, $relative = false,
'disabled'); 'disabled');
@ -61,4 +61,40 @@ abstract class PhabricatorProjectController extends PhabricatorController {
return $nav_view; return $nav_view;
} }
public function buildApplicationMenu() {
return $this->buildSideNavView(null, true)->getMenu();
}
public function buildSideNavView($filter = null, $for_app = false) {
$user = $this->getRequest()->getUser();
$nav = new AphrontSideNavFilterView();
$nav
->setBaseURI(new PhutilURI('/project/filter/'))
->addLabel(pht('User'))
->addFilter('active', pht('Active'))
->addLabel(pht('All'))
->addFilter('all', pht('All Projects'))
->addFilter('allactive', pht('Active Projects'))
->selectFilter($filter, 'active');
if ($for_app) {
$nav->addFilter('create/', pht('Create Project'));
}
return $nav;
}
public function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
$crumbs->addAction(
id(new PhabricatorMenuItemView())
->setName(pht('Create Project'))
->setHref($this->getApplicationURI('create/'))
->setIcon('create'));
return $crumbs;
}
} }

View file

@ -63,7 +63,7 @@ final class PhabricatorProjectCreateController
$error_view = null; $error_view = null;
if ($errors) { if ($errors) {
$error_view = new AphrontErrorView(); $error_view = new AphrontErrorView();
$error_view->setTitle('Form Errors'); $error_view->setTitle(pht('Form Errors'));
$error_view->setErrors($errors); $error_view->setErrors($errors);
} }
@ -77,13 +77,13 @@ final class PhabricatorProjectCreateController
$form $form
->appendChild( ->appendChild(
id(new AphrontFormTextControl()) id(new AphrontFormTextControl())
->setLabel('Name') ->setLabel(pht('Name'))
->setName('name') ->setName('name')
->setValue($project->getName()) ->setValue($project->getName())
->setError($e_name)) ->setError($e_name))
->appendChild( ->appendChild(
id(new AphrontFormTextAreaControl()) id(new AphrontFormTextAreaControl())
->setLabel('Blurb') ->setLabel(pht('Blurb'))
->setName('blurb') ->setName('blurb')
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT) ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
->setValue($profile->getBlurb())); ->setValue($profile->getBlurb()));
@ -92,10 +92,10 @@ final class PhabricatorProjectCreateController
$dialog = id(new AphrontDialogView()) $dialog = id(new AphrontDialogView())
->setUser($user) ->setUser($user)
->setWidth(AphrontDialogView::WIDTH_FORM) ->setWidth(AphrontDialogView::WIDTH_FORM)
->setTitle('Create a New Project') ->setTitle(pht('Create a New Project'))
->appendChild($error_view) ->appendChild($error_view)
->appendChild($form) ->appendChild($form)
->addSubmitButton('Create Project') ->addSubmitButton(pht('Create Project'))
->addCancelButton('/project/'); ->addCancelButton('/project/');
return id(new AphrontDialogResponse())->setDialog($dialog); return id(new AphrontDialogResponse())->setDialog($dialog);
@ -104,22 +104,32 @@ final class PhabricatorProjectCreateController
$form $form
->appendChild( ->appendChild(
id(new AphrontFormSubmitControl()) id(new AphrontFormSubmitControl())
->setValue('Create') ->setValue(pht('Create'))
->addCancelButton('/project/')); ->addCancelButton('/project/'));
$panel = new AphrontPanelView(); $panel = new AphrontPanelView();
$panel $panel
->setWidth(AphrontPanelView::WIDTH_FORM) ->setWidth(AphrontPanelView::WIDTH_FORM)
->setHeader('Create a New Project') ->setHeader(pht('Create a New Project'))
->setNoBackground()
->appendChild($form); ->appendChild($form);
return $this->buildStandardPageResponse( $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView());
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('Create Project'))
->setHref($this->getApplicationURI().'create/')
);
return $this->buildApplicationPage(
array( array(
$crumbs,
$error_view, $error_view,
$panel, $panel,
), ),
array( array(
'title' => 'Create new Project', 'title' => pht('Create New Project'),
'device' => true
)); ));
} }
} }

View file

@ -12,14 +12,7 @@ final class PhabricatorProjectListController
public function processRequest() { public function processRequest() {
$request = $this->getRequest(); $request = $this->getRequest();
$nav = new AphrontSideNavFilterView(); $nav = $this->buildSideNavView($this->filter);
$nav
->setBaseURI(new PhutilURI('/project/filter/'))
->addLabel('User')
->addFilter('active', 'Active')
->addLabel('All')
->addFilter('all', 'All Projects')
->addFilter('allactive','Active Projects');
$this->filter = $nav->selectFilter($this->filter, 'active'); $this->filter = $nav->selectFilter($this->filter, 'active');
$pager = new AphrontPagerView(); $pager = new AphrontPagerView();
@ -33,21 +26,19 @@ final class PhabricatorProjectListController
$view_phid = $request->getUser()->getPHID(); $view_phid = $request->getUser()->getPHID();
$status_filter = PhabricatorProjectQuery::STATUS_ANY;
switch ($this->filter) { switch ($this->filter) {
case 'active': case 'active':
$table_header = 'Your Projects'; $table_header = pht('Your Projects');
$query->withMemberPHIDs(array($view_phid)); $query->withMemberPHIDs(array($view_phid));
$query->withStatus(PhabricatorProjectQuery::STATUS_ACTIVE); $query->withStatus(PhabricatorProjectQuery::STATUS_ACTIVE);
break; break;
case 'allactive': case 'allactive':
$status_filter = PhabricatorProjectQuery::STATUS_ACTIVE; $table_header = pht('Active Projects');
$table_header = 'Active Projects'; $query->withStatus(PhabricatorProjectQuery::STATUS_ACTIVE);
// fallthrough break;
case 'all': case 'all':
$table_header = 'All Projects'; $table_header = pht('All Projects');
$query->withStatus($status_filter); $query->withStatus(PhabricatorProjectQuery::STATUS_ANY);
break; break;
} }
@ -122,11 +113,11 @@ final class PhabricatorProjectListController
$table = new AphrontTableView($rows); $table = new AphrontTableView($rows);
$table->setHeaders( $table->setHeaders(
array( array(
'Project', pht('Project'),
'Status', pht('Status'),
'Description', pht('Description'),
'Population', pht('Population'),
'Open Tasks', pht('Open Tasks'),
)); ));
$table->setColumnClasses( $table->setColumnClasses(
array( array(
@ -139,16 +130,25 @@ final class PhabricatorProjectListController
$panel = new AphrontPanelView(); $panel = new AphrontPanelView();
$panel->setHeader($table_header); $panel->setHeader($table_header);
$panel->setCreateButton('Create New Project', '/project/create/');
$panel->appendChild($table); $panel->appendChild($table);
$panel->setNoBackground();
$panel->appendChild($pager); $panel->appendChild($pager);
$nav->appendChild($panel); $nav->appendChild($panel);
return $this->buildStandardPageResponse( $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView());
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($table_header)
->setHref($this->getApplicationURI())
);
$nav->setCrumbs($crumbs);
return $this->buildApplicationPage(
$nav, $nav,
array( array(
'title' => 'Projects', 'title' => pht('Projects'),
'device' => true,
)); ));
} }
} }

View file

@ -83,8 +83,8 @@ final class PhabricatorProjectMembersEditController
); );
} }
$header_name = 'Edit Members'; $header_name = pht('Edit Members');
$title = 'Edit Members'; $title = pht('Edit Members');
$list = $this->renderMemberList($handles); $list = $this->renderMemberList($handles);
@ -94,23 +94,24 @@ final class PhabricatorProjectMembersEditController
->appendChild( ->appendChild(
id(new AphrontFormTokenizerControl()) id(new AphrontFormTokenizerControl())
->setName('phids') ->setName('phids')
->setLabel('Add Members') ->setLabel(pht('Add Members'))
->setDatasource('/typeahead/common/users/')) ->setDatasource('/typeahead/common/users/'))
->appendChild( ->appendChild(
id(new AphrontFormSubmitControl()) id(new AphrontFormSubmitControl())
->addCancelButton('/project/view/'.$project->getID().'/') ->addCancelButton('/project/view/'.$project->getID().'/')
->setValue('Add Members')); ->setValue(pht('Add Members')));
$faux_form = id(new AphrontFormLayoutView()) $faux_form = id(new AphrontFormLayoutView())
->setBackgroundShading(true) ->setBackgroundShading(true)
->setPadded(true) ->setPadded(true)
->appendChild( ->appendChild(
id(new AphrontFormInsetView()) id(new AphrontFormInsetView())
->setTitle('Current Members ('.count($handles).')') ->setTitle(pht('Current Members (%d)', count($handles)))
->appendChild($list)); ->appendChild($list));
$panel = new AphrontPanelView(); $panel = new AphrontPanelView();
$panel->setHeader($header_name); $panel->setHeader($header_name);
$panel->setWidth(AphrontPanelView::WIDTH_FORM); $panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->setNoBackground();
$panel->appendChild($form); $panel->appendChild($form);
$panel->appendChild('<br />'); $panel->appendChild('<br />');
$panel->appendChild($faux_form); $panel->appendChild($faux_form);
@ -119,10 +120,24 @@ final class PhabricatorProjectMembersEditController
$nav->selectFilter('members'); $nav->selectFilter('members');
$nav->appendChild($panel); $nav->appendChild($panel);
return $this->buildStandardPageResponse( $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView());
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($project->getName())
->setHref('/project/view/'.$project->getID().'/')
);
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('Edit Members'))
->setHref($this->getApplicationURI())
);
$nav->setCrumbs($crumbs);
return $this->buildApplicationPage(
$nav, $nav,
array( array(
'title' => $title, 'title' => $title,
'device' => true,
)); ));
} }

View file

@ -5,6 +5,7 @@ final class PhabricatorProjectProfileController
private $id; private $id;
private $page; private $page;
private $project;
public function willProcessRequest(array $data) { public function willProcessRequest(array $data) {
$this->id = idx($data, 'id'); $this->id = idx($data, 'id');
@ -24,6 +25,7 @@ final class PhabricatorProjectProfileController
} }
$project = $query->executeOne(); $project = $query->executeOne();
$this->project = $project;
if (!$project) { if (!$project) {
return new Aphront404Response(); return new Aphront404Response();
} }
@ -96,7 +98,7 @@ final class PhabricatorProjectProfileController
array( array(
'class' => $class, 'class' => $class,
), ),
'Join Project')); pht('Join Project')));
} else { } else {
$action = javelin_tag( $action = javelin_tag(
'a', 'a',
@ -105,7 +107,7 @@ final class PhabricatorProjectProfileController
'sigil' => 'workflow', 'sigil' => 'workflow',
'class' => 'grey button', 'class' => 'grey button',
), ),
'Leave Project...'); pht('Leave Project...'));
} }
$header->addAction($action); $header->addAction($action);
@ -115,10 +117,10 @@ final class PhabricatorProjectProfileController
$content = '<div style="padding: 1em;">'.$content.'</div>'; $content = '<div style="padding: 1em;">'.$content.'</div>';
$header->appendChild($content); $header->appendChild($content);
return $this->buildStandardPageResponse( return $this->buildApplicationPage(
$nav_view, $nav_view,
array( array(
'title' => $project->getName().' Project', 'title' => pht('%s Project', $project->getName()),
)); ));
} }
@ -143,11 +145,11 @@ final class PhabricatorProjectProfileController
<div class="phabricator-profile-info-pane"> <div class="phabricator-profile-info-pane">
<table class="phabricator-profile-info-table"> <table class="phabricator-profile-info-table">
<tr> <tr>
<th>Creator</th> <th>%s</th>
<td>%s</td> <td>%s</td>
</tr> </tr>
<tr> <tr>
<th>Created</th> <th>%s</th>
<td>%s</td> <td>%s</td>
</tr> </tr>
<tr> <tr>
@ -155,15 +157,18 @@ final class PhabricatorProjectProfileController
<td>%s</td> <td>%s</td>
</tr> </tr>
<tr> <tr>
<th>Blurb</th> <th>%s</th>
<td>%s</td> <td>%s</td>
</tr> </tr>
</table> </table>
</div> </div>
</div>', </div>',
pht('Creator'),
$handles[$project->getAuthorPHID()]->renderLink(), $handles[$project->getAuthorPHID()]->renderLink(),
pht('Created'),
$timestamp, $timestamp,
$project->getPHID(), $project->getPHID(),
pht('Blurb'),
$blurb); $blurb);
return $about; return $about;
@ -184,12 +189,15 @@ final class PhabricatorProjectProfileController
if ($affiliated) { if ($affiliated) {
$affiliated = '<ul>'.implode("\n", $affiliated).'</ul>'; $affiliated = '<ul>'.implode("\n", $affiliated).'</ul>';
} else { } else {
$affiliated = '<p><em>No one is affiliated with this project.</em></p>'; $affiliated =
'<p><em>'.
pht('No one is affiliated with this project.').
'</em></p>';
} }
return return
'<div class="phabricator-profile-info-group">'. '<div class="phabricator-profile-info-group">'.
'<h1 class="phabricator-profile-info-header">People</h1>'. '<h1 class="phabricator-profile-info-header">'.pht('People').'</h1>'.
'<div class="phabricator-profile-info-pane">'. '<div class="phabricator-profile-info-pane">'.
$affiliated. $affiliated.
'</div>'. '</div>'.
@ -207,7 +215,7 @@ final class PhabricatorProjectProfileController
$stories = $query->execute(); $stories = $query->execute();
if (!$stories) { if (!$stories) {
return 'There are no stories about this project.'; return pht('There are no stories about this project.');
} }
return $this->renderStories($stories); return $this->renderStories($stories);
@ -222,7 +230,9 @@ final class PhabricatorProjectProfileController
return return
'<div class="phabricator-profile-info-group">'. '<div class="phabricator-profile-info-group">'.
'<h1 class="phabricator-profile-info-header">Activity Feed</h1>'. '<h1 class="phabricator-profile-info-header">'.
pht('Activity Feed').
'</h1>'.
'<div class="phabricator-profile-info-pane">'. '<div class="phabricator-profile-info-pane">'.
$view->render(). $view->render().
'</div>'. '</div>'.
@ -257,7 +267,7 @@ final class PhabricatorProjectProfileController
} }
if (empty($tasks)) { if (empty($tasks)) {
$task_views = '<em>No open tasks.</em>'; $task_views = '<em>'.pht('No open tasks.').'</em>';
} else { } else {
$task_views = implode('', $task_views); $task_views = implode('', $task_views);
} }
@ -269,12 +279,12 @@ final class PhabricatorProjectProfileController
array( array(
'href' => '/maniphest/view/all/?projects='.$project->getPHID(), 'href' => '/maniphest/view/all/?projects='.$project->getPHID(),
), ),
"View All Open Tasks \xC2\xBB"); pht("View All Open Tasks \xC2\xBB"));
$content = $content =
'<div class="phabricator-profile-info-group"> '<div class="phabricator-profile-info-group">
<h1 class="phabricator-profile-info-header">'. <h1 class="phabricator-profile-info-header">'.
"Open Tasks ({$open})". pht("Open Tasks (%d)", $open).
'</h1>'. '</h1>'.
'<div class="phabricator-profile-info-pane">'. '<div class="phabricator-profile-info-pane">'.
$task_views. $task_views.

View file

@ -86,8 +86,8 @@ final class PhabricatorProjectProfileEditController
$profile->setBlurb($request->getStr('blurb')); $profile->setBlurb($request->getStr('blurb'));
if (!strlen($project->getName())) { if (!strlen($project->getName())) {
$e_name = 'Required'; $e_name = pht('Required');
$errors[] = 'Project name is required.'; $errors[] = pht('Project name is required.');
} else { } else {
$e_name = null; $e_name = null;
} }
@ -112,9 +112,9 @@ final class PhabricatorProjectProfileEditController
$y = 50); $y = 50);
$profile->setProfileImagePHID($xformed->getPHID()); $profile->setProfileImagePHID($xformed->getPHID());
} else { } else {
$e_image = 'Not Supported'; $e_image = pht('Not Supported');
$errors[] = $errors[] =
'This server only supports these image formats: '. pht('This server only supports these image formats:').' '.
implode(', ', $supported_formats).'.'; implode(', ', $supported_formats).'.';
} }
} }
@ -132,12 +132,12 @@ final class PhabricatorProjectProfileEditController
$error_view = null; $error_view = null;
if ($errors) { if ($errors) {
$error_view = new AphrontErrorView(); $error_view = new AphrontErrorView();
$error_view->setTitle('Form Errors'); $error_view->setTitle(pht('Form Errors'));
$error_view->setErrors($errors); $error_view->setErrors($errors);
} }
$header_name = 'Edit Project'; $header_name = pht('Edit Project');
$title = 'Edit Project'; $title = pht('Edit Project');
$action = '/project/edit/'.$project->getID().'/'; $action = '/project/edit/'.$project->getID().'/';
$policies = id(new PhabricatorPolicyQuery()) $policies = id(new PhabricatorPolicyQuery())
@ -153,30 +153,30 @@ final class PhabricatorProjectProfileEditController
->setEncType('multipart/form-data') ->setEncType('multipart/form-data')
->appendChild( ->appendChild(
id(new AphrontFormTextControl()) id(new AphrontFormTextControl())
->setLabel('Name') ->setLabel(pht('Name'))
->setName('name') ->setName('name')
->setValue($project->getName()) ->setValue($project->getName())
->setError($e_name)) ->setError($e_name))
->appendChild( ->appendChild(
id(new AphrontFormSelectControl()) id(new AphrontFormSelectControl())
->setLabel('Project Status') ->setLabel(pht('Project Status'))
->setName('status') ->setName('status')
->setOptions($options) ->setOptions($options)
->setValue($project->getStatus())) ->setValue($project->getStatus()))
->appendChild( ->appendChild(
id(new AphrontFormTextAreaControl()) id(new AphrontFormTextAreaControl())
->setLabel('Blurb') ->setLabel(pht('Blurb'))
->setName('blurb') ->setName('blurb')
->setValue($profile->getBlurb())) ->setValue($profile->getBlurb()))
->appendChild(hsprintf( ->appendChild('<p class="aphront-form-instructions">'.
'<p class="aphront-form-instructions">NOTE: Policy settings are not '. pht('NOTE: Policy settings are not yet fully implemented. '.
'yet fully implemented. Some interfaces still ignore these settings, '. 'Some interfaces still ignore these settings, '.
'particularly "Visible To".</p>')) 'particularly "Visible To".').'</p>')
->appendChild( ->appendChild(
id(new AphrontFormPolicyControl()) id(new AphrontFormPolicyControl())
->setUser($user) ->setUser($user)
->setName('can_view') ->setName('can_view')
->setCaption('Members can always view a project.') ->setCaption(pht('Members can always view a project.'))
->setPolicyObject($project) ->setPolicyObject($project)
->setPolicies($policies) ->setPolicies($policies)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)) ->setCapability(PhabricatorPolicyCapability::CAN_VIEW))
@ -192,13 +192,13 @@ final class PhabricatorProjectProfileEditController
->setUser($user) ->setUser($user)
->setName('can_join') ->setName('can_join')
->setCaption( ->setCaption(
'Users who can edit a project can always join a project.') pht('Users who can edit a project can always join a project.'))
->setPolicyObject($project) ->setPolicyObject($project)
->setPolicies($policies) ->setPolicies($policies)
->setCapability(PhabricatorPolicyCapability::CAN_JOIN)) ->setCapability(PhabricatorPolicyCapability::CAN_JOIN))
->appendChild( ->appendChild(
id(new AphrontFormMarkupControl()) id(new AphrontFormMarkupControl())
->setLabel('Profile Image') ->setLabel(pht('Profile Image'))
->setValue( ->setValue(
phutil_tag( phutil_tag(
'img', 'img',
@ -207,18 +207,20 @@ final class PhabricatorProjectProfileEditController
)))) ))))
->appendChild( ->appendChild(
id(new AphrontFormImageControl()) id(new AphrontFormImageControl())
->setLabel('Change Image') ->setLabel(pht('Change Image'))
->setName('image') ->setName('image')
->setError($e_image) ->setError($e_image)
->setCaption('Supported formats: '.implode(', ', $supported_formats))) ->setCaption(
pht('Supported formats:').' '.implode(', ', $supported_formats)))
->appendChild( ->appendChild(
id(new AphrontFormSubmitControl()) id(new AphrontFormSubmitControl())
->addCancelButton('/project/view/'.$project->getID().'/') ->addCancelButton('/project/view/'.$project->getID().'/')
->setValue('Save')); ->setValue(pht('Save')));
$panel = new AphrontPanelView(); $panel = new AphrontPanelView();
$panel->setHeader($header_name); $panel->setHeader($header_name);
$panel->setWidth(AphrontPanelView::WIDTH_FORM); $panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->setNoBackground();
$panel->appendChild($form); $panel->appendChild($form);
$nav = $this->buildLocalNavigation($project); $nav = $this->buildLocalNavigation($project);
@ -229,10 +231,24 @@ final class PhabricatorProjectProfileEditController
$panel, $panel,
)); ));
return $this->buildStandardPageResponse( $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView());
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($project->getName())
->setHref('/project/view/'.$project->getID().'/')
);
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('Edit Project'))
->setHref($this->getApplicationURI())
);
$nav->setCrumbs($crumbs);
return $this->buildApplicationPage(
$nav, $nav,
array( array(
'title' => $title, 'title' => $title,
'device' => true,
)); ));
} }
} }

View file

@ -61,12 +61,14 @@ final class PhabricatorProjectUpdateController
case 'leave': case 'leave':
$dialog = new AphrontDialogView(); $dialog = new AphrontDialogView();
$dialog->setUser($user); $dialog->setUser($user);
$dialog->setTitle('Really leave project?'); $dialog->setTitle(pht('Really leave project?'));
$dialog->appendChild( $dialog->appendChild(
'<p>Your tremendous contributions to this project will be sorely '. '<p>'.
'missed. Are you sure you want to leave?</p>'); pht('Your tremendous contributions to this project will be sorely '.
'missed. Are you sure you want to leave?').
'</p>');
$dialog->addCancelButton($project_uri); $dialog->addCancelButton($project_uri);
$dialog->addSubmitButton('Leave Project'); $dialog->addSubmitButton(pht('Leave Project'));
break; break;
default: default:
return new Aphront404Response(); return new Aphront404Response();

View file

@ -164,7 +164,8 @@ final class PhabricatorProjectEditor extends PhabricatorEditor {
if ($slug == '/') { if ($slug == '/') {
throw new PhabricatorProjectNameCollisionException( throw new PhabricatorProjectNameCollisionException(
"Project names must be unique and contain some letters or numbers."); pht("Project names must be unique and contain some ".
"letters or numbers."));
} }
$id = $project->getID(); $id = $project->getID();