Skip to content

Commit 9ad9ac9

Browse files
author
epriestley
committedApr 12, 2019
On Dashboard tab panels in edit mode, make the "Tab Name" and the "Dropdown Edit Caret" into different links
Summary: Ref T13272. In edit mode, tab panels now have a dropdown menu. However, this sort of overrlaps with the actual action of clicking the tab to select it. Separate these into different click targets so that "select tab X" and "open dropdown menu for X" are different operations. This is more work than it appears because: - We have an "action icon" already, used when you put a dashboard on a portal/home to create an "Edit" link. It makes sense to attach dropdowns to this, but it has some hard-coded stuff. - In applications with a "Create <thing>" in the crumbs (like Maniphest), we may use a dropdown menu if there are multiple create forms available. However, this menu renders in a weird way by reading all the properties out of an actual "View" object and building something else. - The "list of tabs" stuff shares code with different "list of tabs" navigation used by Diffusion and Instances. ..but I think I fixed everything and didn't break anything. Test Plan: - Clicked "select tab" and "open dropdown menu" as separate actions. - Viewed Diffusion, Maniphest with multiple create forms, Instances. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13272 Differential Revision: https://secure.phabricator.com/D20396
1 parent d02256d commit 9ad9ac9

10 files changed

+135
-113
lines changed
 

‎resources/celerity/map.php

+13-13
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
'names' => array(
1010
'conpherence.pkg.css' => '3c8a0668',
1111
'conpherence.pkg.js' => '020aebcf',
12-
'core.pkg.css' => 'dacb981b',
13-
'core.pkg.js' => 'c783d8f6',
12+
'core.pkg.css' => '9d654dff',
13+
'core.pkg.js' => '350acda5',
1414
'differential.pkg.css' => '8d8360fb',
1515
'differential.pkg.js' => '67e02996',
1616
'diffusion.pkg.css' => '42c75c37',
@@ -134,7 +134,7 @@
134134
'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '490e2e2e',
135135
'rsrc/css/phui/object-item/phui-oi-list-view.css' => 'f14f2422',
136136
'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => '6a30fa46',
137-
'rsrc/css/phui/phui-action-list.css' => '8862282e',
137+
'rsrc/css/phui/phui-action-list.css' => '48a45c51',
138138
'rsrc/css/phui/phui-action-panel.css' => '6c386cbf',
139139
'rsrc/css/phui/phui-badge.css' => '666e25ad',
140140
'rsrc/css/phui/phui-basic-nav-view.css' => '56ebd66d',
@@ -164,7 +164,7 @@
164164
'rsrc/css/phui/phui-invisible-character-view.css' => 'c694c4a4',
165165
'rsrc/css/phui/phui-left-right.css' => '68513c34',
166166
'rsrc/css/phui/phui-lightbox.css' => '4ebf22da',
167-
'rsrc/css/phui/phui-list.css' => '470b1adb',
167+
'rsrc/css/phui/phui-list.css' => '734a1039',
168168
'rsrc/css/phui/phui-object-box.css' => 'f434b6be',
169169
'rsrc/css/phui/phui-pager.css' => 'd022c7ad',
170170
'rsrc/css/phui/phui-pinboard-view.css' => '1f08f5d8',
@@ -374,7 +374,7 @@
374374
'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => '09ecf50c',
375375
'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => '076bd092',
376376
'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '1e413dc9',
377-
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '9b1cbd76',
377+
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '8d4490a2',
378378
'rsrc/js/application/diff/DiffChangeset.js' => 'd0a85a85',
379379
'rsrc/js/application/diff/DiffChangesetList.js' => '04023d82',
380380
'rsrc/js/application/diff/DiffInline.js' => 'a4a14a94',
@@ -597,7 +597,7 @@
597597
'javelin-behavior-dashboard-async-panel' => '09ecf50c',
598598
'javelin-behavior-dashboard-move-panels' => '076bd092',
599599
'javelin-behavior-dashboard-query-panel-select' => '1e413dc9',
600-
'javelin-behavior-dashboard-tab-panel' => '9b1cbd76',
600+
'javelin-behavior-dashboard-tab-panel' => '8d4490a2',
601601
'javelin-behavior-day-view' => '727a5a61',
602602
'javelin-behavior-desktop-notifications-control' => '070679fe',
603603
'javelin-behavior-detect-timezone' => '78bc5d94',
@@ -757,7 +757,7 @@
757757
'path-typeahead' => 'ad486db3',
758758
'people-picture-menu-item-css' => 'fe8e07cf',
759759
'people-profile-css' => '2ea2daa1',
760-
'phabricator-action-list-view-css' => '8862282e',
760+
'phabricator-action-list-view-css' => '48a45c51',
761761
'phabricator-busy' => '5202e831',
762762
'phabricator-chatlog-css' => 'abdc76ee',
763763
'phabricator-content-source-view-css' => 'cdf0d579',
@@ -847,7 +847,7 @@
847847
'phui-invisible-character-view-css' => 'c694c4a4',
848848
'phui-left-right-css' => '68513c34',
849849
'phui-lightbox-css' => '4ebf22da',
850-
'phui-list-view-css' => '470b1adb',
850+
'phui-list-view-css' => '734a1039',
851851
'phui-object-box-css' => 'f434b6be',
852852
'phui-oi-big-ui-css' => 'fa74cc35',
853853
'phui-oi-color-css' => 'b517bfa0',
@@ -1644,6 +1644,11 @@
16441644
'phabricator-shaped-request',
16451645
'conpherence-thread-manager',
16461646
),
1647+
'8d4490a2' => array(
1648+
'javelin-behavior',
1649+
'javelin-dom',
1650+
'javelin-stratcom',
1651+
),
16471652
'8e0aa661' => array(
16481653
'javelin-install',
16491654
'javelin-dom',
@@ -1736,11 +1741,6 @@
17361741
'javelin-install',
17371742
'javelin-util',
17381743
),
1739-
'9b1cbd76' => array(
1740-
'javelin-behavior',
1741-
'javelin-dom',
1742-
'javelin-stratcom',
1743-
),
17441744
'9cec214e' => array(
17451745
'javelin-behavior',
17461746
'javelin-stratcom',

‎src/applications/dashboard/controller/panel/PhabricatorDashboardPanelViewController.php

+8-51
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ public function handleRequest(AphrontRequest $request) {
1919
return new Aphront404Response();
2020
}
2121

22+
$can_edit = PhabricatorPolicyFilter::hasCapability(
23+
$viewer,
24+
$panel,
25+
PhabricatorPolicyCapability::CAN_EDIT);
26+
2227
$title = $panel->getMonogram().' '.$panel->getName();
2328
$crumbs = $this->buildApplicationCrumbs();
2429
$crumbs->addTextCrumb(
@@ -29,7 +34,6 @@ public function handleRequest(AphrontRequest $request) {
2934

3035
$header = $this->buildHeaderView($panel);
3136
$curtain = $this->buildCurtainView($panel);
32-
$properties = $this->buildPropertyView($panel);
3337

3438
$timeline = $this->buildTransactionTimeline(
3539
$panel,
@@ -40,6 +44,7 @@ public function handleRequest(AphrontRequest $request) {
4044
->setPanel($panel)
4145
->setPanelPHID($panel->getPHID())
4246
->setParentPanelPHIDs(array())
47+
->setEditMode(true)
4348
->renderPanel();
4449

4550
$preview = id(new PHUIBoxView())
@@ -50,10 +55,9 @@ public function handleRequest(AphrontRequest $request) {
5055
->setHeader($header)
5156
->setCurtain($curtain)
5257
->setMainColumn(array(
53-
$properties,
58+
$rendered_panel,
5459
$timeline,
55-
))
56-
->setFooter($rendered_panel);
60+
));
5761

5862
return $this->newPage()
5963
->setTitle($title)
@@ -124,51 +128,4 @@ private function buildCurtainView(PhabricatorDashboardPanel $panel) {
124128
return $curtain;
125129
}
126130

127-
private function buildPropertyView(PhabricatorDashboardPanel $panel) {
128-
$viewer = $this->getViewer();
129-
130-
$properties = id(new PHUIPropertyListView())
131-
->setUser($viewer);
132-
133-
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
134-
$viewer,
135-
$panel);
136-
137-
$panel_type = $panel->getImplementation();
138-
if ($panel_type) {
139-
$type_name = $panel_type->getPanelTypeName();
140-
} else {
141-
$type_name = phutil_tag(
142-
'em',
143-
array(),
144-
nonempty($panel->getPanelType(), pht('null')));
145-
}
146-
147-
$properties->addProperty(
148-
pht('Panel Type'),
149-
$type_name);
150-
151-
$properties->addProperty(
152-
pht('Editable By'),
153-
$descriptions[PhabricatorPolicyCapability::CAN_EDIT]);
154-
155-
$dashboard_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
156-
$panel->getPHID(),
157-
PhabricatorDashboardPanelHasDashboardEdgeType::EDGECONST);
158-
159-
$does_not_appear = pht(
160-
'This panel does not appear on any dashboards.');
161-
162-
$properties->addProperty(
163-
pht('Appears On'),
164-
$dashboard_phids
165-
? $viewer->renderHandleList($dashboard_phids)
166-
: phutil_tag('em', array(), $does_not_appear));
167-
168-
return id(new PHUIObjectBoxView())
169-
->setHeaderText(pht('Details'))
170-
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
171-
->addPropertyList($properties);
172-
}
173-
174131
}

‎src/applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ final class PhabricatorDashboardPanelRenderingEngine extends Phobject {
1515
private $dashboardID;
1616
private $movable = true;
1717
private $panelHandle;
18+
private $editMode;
1819

1920
public function setDashboardID($id) {
2021
$this->dashboardID = $id;
@@ -44,7 +45,12 @@ public function getPanelHandle() {
4445
}
4546

4647
public function isEditMode() {
47-
return ($this->getHeaderMode() === self::HEADER_MODE_EDIT);
48+
return $this->editMode;
49+
}
50+
51+
public function setEditMode($mode) {
52+
$this->editMode = $mode;
53+
return $this;
4854
}
4955

5056
/**

‎src/applications/dashboard/engine/PhabricatorDashboardRenderingEngine.php

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public function renderDashboard() {
7676
->setPanelPHID($panel_phid)
7777
->setParentPanelPHIDs(array())
7878
->setHeaderMode($h_mode)
79+
->setEditMode($is_editable)
7980
->setPanelHandle($handles[$panel_phid]);
8081

8182
$panel = idx($panels, $panel_phid);

‎src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php

+6-2
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,9 @@ public function renderPanelContent(
166166
->setHref($details_uri)
167167
->setDisabled(!$subpanel));
168168

169-
$tab_view->setDropdownMenu($dropdown_menu);
169+
$tab_view
170+
->setActionIcon('fa-caret-down', '#')
171+
->setDropdownMenu($dropdown_menu);
170172
}
171173

172174
$list->addMenuItem($tab_view);
@@ -193,8 +195,10 @@ public function renderPanelContent(
193195
$list->addMenuItem(
194196
id(new PHUIListItemView())
195197
->setHref('#')
198+
->setDisabled(true)
196199
->setSelected(false)
197-
->setName(pht('Add Tab...'))
200+
->setName(pht("\xC2\xB7 \xC2\xB7 \xC2\xB7"))
201+
->setActionIcon('fa-caret-down', '#')
198202
->setDropdownMenu($actions));
199203
}
200204

‎src/view/phui/PHUICrumbsView.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,15 @@ public function render() {
5050

5151
$action_view = null;
5252
if ($this->actions) {
53+
// TODO: This block of code takes "PHUIListItemView" objects and turns
54+
// them into some weird abomination by reading most of their properties
55+
// out. Some day, this workflow should render the items and CSS should
56+
// resytle them in place without needing a wholly separate set of
57+
// DOM nodes.
58+
5359
$actions = array();
5460
foreach ($this->actions as $action) {
55-
if ($action->getType() == PHUIListItemView::TYPE_DIVIDER) {
61+
if ($action->getType() == PHUIListItemView::TYPE_DIVIDER) {
5662
$actions[] = phutil_tag(
5763
'span',
5864
array(

‎src/view/phui/PHUIListItemView.php

+55-27
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ final class PHUIListItemView extends AphrontTagView {
3535
private $actionIconHref;
3636
private $count;
3737
private $rel;
38-
private $hasDropdown;
38+
private $dropdownMenu;
3939

4040
public function setOpenInNewWindow($open_in_new_window) {
4141
$this->openInNewWindow = $open_in_new_window;
@@ -65,11 +65,19 @@ public function getHideInApplicationMenu() {
6565
}
6666

6767
public function setDropdownMenu(PhabricatorActionListView $actions) {
68-
Javelin::initBehavior('phui-dropdown-menu');
6968

70-
$this->addSigil('phui-dropdown-menu');
71-
$this->setMetadata($actions->getDropdownMenuMetadata());
72-
$this->hasDropdown = true;
69+
$this->dropdownMenu = $actions;
70+
71+
// TODO: "PHUICrumbsView" currently creates a bad copy of list items
72+
// by reading some of their properties. To survive this copy step, we
73+
// need to mutate "$this" immediately or the "Create Object" dropdown
74+
// when multiple create forms exist breaks.
75+
76+
if (!$this->actionIcon) {
77+
Javelin::initBehavior('phui-dropdown-menu');
78+
$this->addSigil('phui-dropdown-menu');
79+
$this->setMetadata($actions->getDropdownMenuMetadata());
80+
}
7381

7482
return $this;
7583
}
@@ -237,12 +245,19 @@ protected function getTagAttributes() {
237245
$classes[] = 'phui-list-item-has-action-icon';
238246
}
239247

240-
if ($this->hasDropdown) {
248+
if ($this->dropdownMenu) {
241249
$classes[] = 'dropdown';
250+
if (!$this->actionIcon) {
251+
throw new Exception(
252+
pht(
253+
'List item views can not currently render a dropdown without '.
254+
'an action icon, because no application uses one. Clean up '.
255+
'PHUICrumbsView, then add this capability.'));
256+
}
242257
}
243258

244259
return array(
245-
'class' => implode(' ', $classes),
260+
'class' => $classes,
246261
);
247262
}
248263

@@ -345,19 +360,7 @@ protected function getTagContent() {
345360
$classes[] = 'phui-list-item-indented';
346361
}
347362

348-
$action_link = null;
349-
if ($this->actionIcon) {
350-
$action_icon = id(new PHUIIconView())
351-
->setIcon($this->actionIcon)
352-
->addClass('phui-list-item-action-icon');
353-
$action_link = phutil_tag(
354-
'a',
355-
array(
356-
'href' => $this->actionIconHref,
357-
'class' => 'phui-list-item-action-href',
358-
),
359-
$action_icon);
360-
}
363+
$action_link = $this->newActionIconView();
361364

362365
$count = null;
363366
if ($this->count) {
@@ -369,12 +372,6 @@ protected function getTagContent() {
369372
$this->count);
370373
}
371374

372-
if ($this->hasDropdown) {
373-
$caret = phutil_tag('span', array('class' => 'caret'), '');
374-
} else {
375-
$caret = null;
376-
}
377-
378375
$icons = $this->getIcons();
379376

380377
$list_item = javelin_tag(
@@ -393,11 +390,42 @@ protected function getTagContent() {
393390
$icons,
394391
$this->renderChildren(),
395392
$name,
396-
$caret,
397393
$count,
398394
));
399395

400396
return array($list_item, $action_link);
401397
}
402398

399+
private function newActionIconView() {
400+
$action_icon = $this->actionIcon;
401+
$action_href = $this->actionIconHref;
402+
403+
if ($action_icon === null) {
404+
return null;
405+
}
406+
407+
$icon_view = id(new PHUIIconView())
408+
->setIcon($action_icon)
409+
->addClass('phui-list-item-action-icon');
410+
411+
if ($this->dropdownMenu) {
412+
Javelin::initBehavior('phui-dropdown-menu');
413+
$sigil = 'phui-dropdown-menu';
414+
$metadata = $this->dropdownMenu->getDropdownMenuMetadata();
415+
} else {
416+
$sigil = null;
417+
$metadata = null;
418+
}
419+
420+
return javelin_tag(
421+
'a',
422+
array(
423+
'href' => $action_href,
424+
'class' => 'phui-list-item-action-href',
425+
'sigil' => $sigil,
426+
'meta' => $metadata,
427+
),
428+
$icon_view);
429+
}
430+
403431
}

0 commit comments

Comments
 (0)
Failed to load comments.