1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-27 01:02:42 +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 {
public function getName() {
return 'Projects';
return pht('Projects');
}
public function getShortDescription() {
return 'Organize Work';
return pht('Organize Work');
}
public function getBaseURI() {

View file

@ -5,7 +5,7 @@ abstract class PhabricatorProjectController extends PhabricatorController {
public function buildStandardPageResponse($view, array $data) {
$page = $this->buildStandardPageView();
$page->setApplicationName('Project');
$page->setApplicationName(pht('Project'));
$page->setBaseURI('/project/');
$page->setTitle(idx($data, 'title'));
$page->setGlyph("\xE2\x98\xA3");
@ -30,29 +30,29 @@ abstract class PhabricatorProjectController extends PhabricatorController {
$edit_uri = '/project/edit/'.$id.'/';
$members_uri = '/project/members/'.$id.'/';
$nav_view->addFilter('dashboard', 'Dashboard');
$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->addFilter('dashboard', pht('Dashboard'));
$nav_view->addFilter('feed', pht('Feed'));
$nav_view->addFilter(null, pht('Tasks').' '.$external_arrow, $tasks_uri);
$nav_view->addFilter(null, pht('Wiki').' '.$external_arrow, $phriction_uri);
$nav_view->addFilter('people', pht('People'));
$nav_view->addFilter('about', pht('About'));
$user = $this->getRequest()->getUser();
$can_edit = PhabricatorPolicyCapability::CAN_EDIT;
if (PhabricatorPolicyFilter::hasCapability($user, $project, $can_edit)) {
$nav_view->addFilter('edit', "Edit Project\xE2\x80\xA6", $edit_uri);
$nav_view->addFilter('members', "Edit Members\xE2\x80\xA6", $members_uri);
$nav_view->addFilter('edit', pht("Edit Project"), $edit_uri);
$nav_view->addFilter('members', pht("Edit Members"), $members_uri);
} else {
$nav_view->addFilter(
'edit',
"Edit Project\xE2\x80\xA6",
pht("Edit Project"),
$edit_uri,
$relative = false,
'disabled');
$nav_view->addFilter(
'members',
"Edit Members\xE2\x80\xA6",
pht("Edit Members"),
$members_uri,
$relative = false,
'disabled');
@ -61,4 +61,40 @@ abstract class PhabricatorProjectController extends PhabricatorController {
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;
if ($errors) {
$error_view = new AphrontErrorView();
$error_view->setTitle('Form Errors');
$error_view->setTitle(pht('Form Errors'));
$error_view->setErrors($errors);
}
@ -77,13 +77,13 @@ final class PhabricatorProjectCreateController
$form
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Name')
->setLabel(pht('Name'))
->setName('name')
->setValue($project->getName())
->setError($e_name))
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Blurb')
->setLabel(pht('Blurb'))
->setName('blurb')
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
->setValue($profile->getBlurb()));
@ -92,10 +92,10 @@ final class PhabricatorProjectCreateController
$dialog = id(new AphrontDialogView())
->setUser($user)
->setWidth(AphrontDialogView::WIDTH_FORM)
->setTitle('Create a New Project')
->setTitle(pht('Create a New Project'))
->appendChild($error_view)
->appendChild($form)
->addSubmitButton('Create Project')
->addSubmitButton(pht('Create Project'))
->addCancelButton('/project/');
return id(new AphrontDialogResponse())->setDialog($dialog);
@ -104,22 +104,32 @@ final class PhabricatorProjectCreateController
$form
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Create')
->setValue(pht('Create'))
->addCancelButton('/project/'));
$panel = new AphrontPanelView();
$panel
->setWidth(AphrontPanelView::WIDTH_FORM)
->setHeader('Create a New Project')
->setHeader(pht('Create a New Project'))
->setNoBackground()
->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(
$crumbs,
$error_view,
$panel,
),
array(
'title' => 'Create new Project',
'title' => pht('Create New Project'),
'device' => true
));
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -164,7 +164,8 @@ final class PhabricatorProjectEditor extends PhabricatorEditor {
if ($slug == '/') {
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();