Skip to content

Commit 7cbe82d

Browse files
author
epriestley
committed
Use modern UI elements and application/event-oriented construction in Projects
Summary: Ref T2715. This partially modernizes projects. Precursor to using ApplicationSearch, which is a precursor to using application PHIDs. Then, some day, we will make projects good. Test Plan: {F51126} Reviewers: btrahan, chad Reviewed By: chad CC: aran Maniphest Tasks: T2715 Differential Revision: https://secure.phabricator.com/D6524
1 parent 3fcd9c9 commit 7cbe82d

8 files changed

+152
-162
lines changed

src/__phutil_library_map__.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,6 +1812,7 @@
18121812
'PhrequentUserTime' => 'applications/phrequent/storage/PhrequentUserTime.php',
18131813
'PhrequentUserTimeQuery' => 'applications/phrequent/query/PhrequentUserTimeQuery.php',
18141814
'PhrictionActionConstants' => 'applications/phriction/constants/PhrictionActionConstants.php',
1815+
'PhrictionActionMenuEventListener' => 'applications/phriction/event/PhrictionActionMenuEventListener.php',
18151816
'PhrictionChangeType' => 'applications/phriction/constants/PhrictionChangeType.php',
18161817
'PhrictionConstants' => 'applications/phriction/constants/PhrictionConstants.php',
18171818
'PhrictionContent' => 'applications/phriction/storage/PhrictionContent.php',
@@ -3850,6 +3851,7 @@
38503851
'PhrequentUserTime' => 'PhrequentDAO',
38513852
'PhrequentUserTimeQuery' => 'PhabricatorOffsetPagedQuery',
38523853
'PhrictionActionConstants' => 'PhrictionConstants',
3854+
'PhrictionActionMenuEventListener' => 'PhutilEventListener',
38533855
'PhrictionChangeType' => 'PhrictionConstants',
38543856
'PhrictionContent' =>
38553857
array(

src/applications/maniphest/event/ManiphestPeopleMenuEventListener.php

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,21 @@ public function handleEvent(PhutilEvent $event) {
1515
}
1616

1717
private function handleActionsEvent($event) {
18-
$person = $event->getValue('object');
19-
if (!($person instanceof PhabricatorUser)) {
20-
return;
21-
}
22-
23-
$href = '/maniphest/view/action/?users='.$person->getPHID();
24-
2518
$actions = $event->getValue('actions');
2619

27-
$actions[] = id(new PhabricatorActionView())
20+
$action = id(new PhabricatorActionView())
2821
->setIcon('maniphest-dark')
2922
->setIconSheet(PHUIIconView::SPRITE_APPS)
30-
->setName(pht('View Tasks'))
31-
->setHref($href);
23+
->setName(pht('View Tasks'));
24+
25+
$object = $event->getValue('object');
26+
if ($object instanceof PhabricatorUser) {
27+
$href = '/maniphest/view/action/?users='.$object->getPHID();
28+
$actions[] = $action->setHref($href);
29+
} else if ($object instanceof PhabricatorProject) {
30+
$href = '/maniphest/view/all/?projects='.$object->getPHID();
31+
$actions[] = $action->setHref($href);
32+
}
3233

3334
$event->setValue('actions', $actions);
3435
}

src/applications/phriction/application/PhabricatorApplicationPhriction.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ public function getRemarkupRules() {
2828
);
2929
}
3030

31+
public function getEventListeners() {
32+
return array(
33+
new PhrictionActionMenuEventListener(),
34+
);
35+
}
36+
3137
public function getRoutes() {
3238
return array(
3339
// Match "/w/" with slug "/".
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
final class PhrictionActionMenuEventListener extends PhutilEventListener {
4+
5+
public function register() {
6+
$this->listen(PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS);
7+
}
8+
9+
public function handleEvent(PhutilEvent $event) {
10+
switch ($event->getType()) {
11+
case PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS:
12+
$this->handleActionsEvent($event);
13+
break;
14+
}
15+
}
16+
17+
private function handleActionsEvent($event) {
18+
$actions = $event->getValue('actions');
19+
20+
$action = id(new PhabricatorActionView())
21+
->setIcon('phriction-dark')
22+
->setIconSheet(PHUIIconView::SPRITE_APPS)
23+
->setName(pht('View Wiki'));
24+
25+
$object = $event->getValue('object');
26+
if ($object instanceof PhabricatorProject) {
27+
$slug = PhabricatorSlug::normalize($object->getPhrictionSlug());
28+
$href = '/w/projects/'.$slug;
29+
$actions[] = $action->setHref($href);
30+
}
31+
32+
$event->setValue('actions', $actions);
33+
}
34+
35+
}

src/applications/project/controller/PhabricatorProjectController.php

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,6 @@
22

33
abstract class PhabricatorProjectController extends PhabricatorController {
44

5-
protected function buildLocalNavigation(PhabricatorProject $project) {
6-
$id = $project->getID();
7-
8-
$nav_view = new AphrontSideNavFilterView();
9-
$uri = new PhutilURI('/project/view/'.$id.'/');
10-
$nav_view->setBaseURI($uri);
11-
12-
$external_arrow = "\xE2\x86\x97";
13-
$tasks_uri = '/maniphest/view/all/?projects='.$project->getPHID();
14-
$slug = PhabricatorSlug::normalize($project->getPhrictionSlug());
15-
$phriction_uri = '/w/projects/'.$slug;
16-
17-
$edit_uri = '/project/edit/'.$id.'/';
18-
$members_uri = '/project/members/'.$id.'/';
19-
20-
$nav_view->addLabel(pht('Project'));
21-
$nav_view->addFilter('dashboard', pht('Dashboard'));
22-
$nav_view->addFilter(null, pht('Tasks').' '.$external_arrow, $tasks_uri);
23-
$nav_view->addFilter(null, pht('Wiki').' '.$external_arrow, $phriction_uri);
24-
25-
$user = $this->getRequest()->getUser();
26-
$can_edit = PhabricatorPolicyCapability::CAN_EDIT;
27-
28-
$nav_view->addLabel(pht('Manage'));
29-
if (PhabricatorPolicyFilter::hasCapability($user, $project, $can_edit)) {
30-
$nav_view->addFilter('edit', pht("Edit Project"), $edit_uri);
31-
$nav_view->addFilter('members', pht("Edit Members"), $members_uri);
32-
} else {
33-
$nav_view->addFilter(
34-
'edit',
35-
pht("Edit Project"),
36-
$edit_uri,
37-
$relative = false,
38-
'disabled');
39-
$nav_view->addFilter(
40-
'members',
41-
pht("Edit Members"),
42-
$members_uri,
43-
$relative = false,
44-
'disabled');
45-
}
46-
47-
return $nav_view;
48-
}
49-
505
public function buildSideNavView($filter = null, $for_app = false) {
516
$user = $this->getRequest()->getUser();
527

src/applications/project/controller/PhabricatorProjectMembersEditController.php

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,6 @@ public function processRequest() {
113113
$box->addPadding(PHUI::PADDING_LARGE);
114114
$box->addMargin(PHUI::MARGIN_LARGE);
115115

116-
$nav = $this->buildLocalNavigation($project);
117-
$nav->selectFilter('members');
118-
$nav->appendChild($form);
119-
$nav->appendChild($box);
120-
121116
$crumbs = $this->buildApplicationCrumbs($this->buildSideNavView());
122117
$crumbs->addCrumb(
123118
id(new PhabricatorCrumbView())
@@ -127,10 +122,13 @@ public function processRequest() {
127122
id(new PhabricatorCrumbView())
128123
->setName(pht('Edit Members'))
129124
->setHref($this->getApplicationURI()));
130-
$nav->setCrumbs($crumbs);
131125

132126
return $this->buildApplicationPage(
133-
$nav,
127+
array(
128+
$crumbs,
129+
$form,
130+
$box,
131+
),
134132
array(
135133
'title' => $title,
136134
'device' => true,

src/applications/project/controller/PhabricatorProjectProfileController.php

Lines changed: 88 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ public function processRequest() {
3434

3535
$picture = $profile->loadProfileImageURI();
3636

37-
$nav_view = $this->buildLocalNavigation($project);
38-
39-
$this->page = $nav_view->selectFilter($this->page, 'dashboard');
40-
4137
require_celerity_resource('phabricator-profile-css');
4238

4339
$tasks = $this->renderTasksPage($project, $profile);
@@ -51,12 +47,10 @@ public function processRequest() {
5147
$query->setViewer($this->getRequest()->getUser());
5248
$stories = $query->execute();
5349
$feed = $this->renderStories($stories);
54-
$about = $this->renderAboutPage($project, $profile);
5550
$people = $this->renderPeoplePage($project, $profile);
56-
$col1 = hsprintf('%s%s', $about, $people);
5751

5852
$content = id(new AphrontMultiColumnView())
59-
->addColumn($col1)
53+
->addColumn($people)
6054
->addColumn($feed)
6155
->setFluidLayout(true);
6256

@@ -70,97 +64,29 @@ public function processRequest() {
7064
->setSubheader(phutil_utf8_shorten($profile->getBlurb(), 1024))
7165
->setImage($picture);
7266

73-
$action = null;
74-
if (!$project->isUserMember($user->getPHID())) {
75-
$can_join = PhabricatorPolicyFilter::hasCapability(
76-
$user,
77-
$project,
78-
PhabricatorPolicyCapability::CAN_JOIN);
79-
80-
$action = id(new PhabricatorActionView())
81-
->setUser($user)
82-
->setRenderAsForm(true)
83-
->setHref('/project/update/'.$project->getID().'/join/')
84-
->setIcon('new')
85-
->setDisabled(!$can_join)
86-
->setName(pht('Join Project'));
87-
} else {
88-
$action = id(new PhabricatorActionView())
89-
->setWorkflow(true)
90-
->setHref('/project/update/'.$project->getID().'/leave/')
91-
->setIcon('delete')
92-
->setName(pht('Leave Project...'));
93-
}
94-
95-
$action_list = id(new PhabricatorActionListView())
96-
->setUser($user)
97-
->setObjectURI($request->getRequestURI())
98-
->addAction($action);
67+
$actions = $this->buildActionListView($project);
68+
$properties = $this->buildPropertyListView($project);
9969

100-
$nav_view->appendChild($header);
101-
$nav_view->appendChild($action_list);
102-
$nav_view->appendChild($content);
70+
$crumbs = $this->buildApplicationCrumbs();
71+
$crumbs->addCrumb(
72+
id(new PhabricatorCrumbView())
73+
->setName($project->getName()));
10374

10475
return $this->buildApplicationPage(
105-
$nav_view,
10676
array(
107-
'title' => pht('%s Project', $project->getName()),
77+
$crumbs,
78+
$header,
79+
$actions,
80+
$properties,
81+
$content,
82+
),
83+
array(
84+
'title' => $project->getName(),
10885
'device' => true,
10986
'dust' => true,
11087
));
11188
}
11289

113-
private function renderAboutPage(
114-
PhabricatorProject $project,
115-
PhabricatorProjectProfile $profile) {
116-
117-
$viewer = $this->getRequest()->getUser();
118-
119-
$blurb = $profile->getBlurb();
120-
$blurb = phutil_escape_html_newlines($blurb);
121-
122-
$phids = array($project->getAuthorPHID());
123-
$phids = array_unique($phids);
124-
$handles = $this->loadViewerHandles($phids);
125-
126-
$timestamp = phabricator_datetime($project->getDateCreated(), $viewer);
127-
128-
$about = hsprintf(
129-
'<div class="phabricator-profile-info-group profile-wrap-responsive">
130-
<h1 class="phabricator-profile-info-header">%s</h1>
131-
<div class="phabricator-profile-info-pane">
132-
<table class="phabricator-profile-info-table">
133-
<tr>
134-
<th>%s</th>
135-
<td>%s</td>
136-
</tr>
137-
<tr>
138-
<th>%s</th>
139-
<td>%s</td>
140-
</tr>
141-
<tr>
142-
<th>PHID</th>
143-
<td>%s</td>
144-
</tr>
145-
<tr>
146-
<th>%s</th>
147-
<td>%s</td>
148-
</tr>
149-
</table>
150-
</div>
151-
</div>',
152-
pht('About This Project'),
153-
pht('Creator'),
154-
$handles[$project->getAuthorPHID()]->renderLink(),
155-
pht('Created'),
156-
$timestamp,
157-
$project->getPHID(),
158-
pht('Blurb'),
159-
$blurb);
160-
161-
return $about;
162-
}
163-
16490
private function renderPeoplePage(
16591
PhabricatorProject $project,
16692
PhabricatorProjectProfile $profile) {
@@ -272,8 +198,79 @@ private function renderTasksPage(
272198
return $content;
273199
}
274200

275-
public function buildApplicationMenu() {
276-
return $this->buildLocalNavigation($this->project)->getMenu();
201+
private function buildActionListView(PhabricatorProject $project) {
202+
$request = $this->getRequest();
203+
$viewer = $request->getUser();
204+
205+
$id = $project->getID();
206+
207+
$view = id(new PhabricatorActionListView())
208+
->setUser($viewer)
209+
->setObject($project)
210+
->setObjectURI($request->getRequestURI());
211+
212+
$can_edit = PhabricatorPolicyFilter::hasCapability(
213+
$viewer,
214+
$project,
215+
PhabricatorPolicyCapability::CAN_EDIT);
216+
217+
$view->addAction(
218+
id(new PhabricatorActionView())
219+
->setName(pht('Edit Project'))
220+
->setIcon('edit')
221+
->setHref($this->getApplicationURI("edit/{$id}/"))
222+
->setDisabled(!$can_edit)
223+
->setWorkflow(!$can_edit));
224+
225+
$view->addAction(
226+
id(new PhabricatorActionView())
227+
->setName(pht('Edit Members'))
228+
->setIcon('edit')
229+
->setHref($this->getApplicationURI("members/{$id}/"))
230+
->setDisabled(!$can_edit)
231+
->setWorkflow(!$can_edit));
232+
233+
234+
$action = null;
235+
if (!$project->isUserMember($viewer->getPHID())) {
236+
$can_join = PhabricatorPolicyFilter::hasCapability(
237+
$viewer,
238+
$project,
239+
PhabricatorPolicyCapability::CAN_JOIN);
240+
241+
$action = id(new PhabricatorActionView())
242+
->setUser($viewer)
243+
->setRenderAsForm(true)
244+
->setHref('/project/update/'.$project->getID().'/join/')
245+
->setIcon('new')
246+
->setDisabled(!$can_join)
247+
->setName(pht('Join Project'));
248+
} else {
249+
$action = id(new PhabricatorActionView())
250+
->setWorkflow(true)
251+
->setHref('/project/update/'.$project->getID().'/leave/')
252+
->setIcon('delete')
253+
->setName(pht('Leave Project...'));
254+
}
255+
$view->addAction($action);
256+
257+
return $view;
258+
}
259+
260+
private function buildPropertyListView(PhabricatorProject $project) {
261+
$request = $this->getRequest();
262+
$viewer = $request->getUser();
263+
264+
$view = id(new PhabricatorPropertyListView())
265+
->setUser($viewer)
266+
->setObject($project);
267+
268+
$view->addProperty(
269+
pht('Created'),
270+
phabricator_datetime($project->getDateCreated(), $viewer));
271+
272+
return $view;
277273
}
278274

275+
279276
}

0 commit comments

Comments
 (0)