2012-12-07 22:32:14 +01:00
|
|
|
<?php
|
|
|
|
|
2013-01-16 19:50:41 +01:00
|
|
|
final class PhabricatorMenuView extends AphrontTagView {
|
2012-12-07 22:32:14 +01:00
|
|
|
|
|
|
|
private $items = array();
|
|
|
|
|
2013-02-03 19:02:35 +01:00
|
|
|
protected function canAppendChild() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-02-05 22:46:02 +01:00
|
|
|
public function newLabel($name, $key = null) {
|
2012-12-07 22:34:44 +01:00
|
|
|
$item = id(new PhabricatorMenuItemView())
|
|
|
|
->setType(PhabricatorMenuItemView::TYPE_LABEL)
|
|
|
|
->setName($name);
|
|
|
|
|
2013-02-06 20:41:57 +01:00
|
|
|
if ($key !== null) {
|
|
|
|
$item->setKey($key);
|
|
|
|
}
|
2012-12-07 22:34:44 +01:00
|
|
|
|
|
|
|
$this->addMenuItem($item);
|
|
|
|
|
|
|
|
return $item;
|
|
|
|
}
|
|
|
|
|
2013-02-05 22:46:02 +01:00
|
|
|
public function newLink($name, $href, $key = null) {
|
2012-12-07 22:34:44 +01:00
|
|
|
$item = id(new PhabricatorMenuItemView())
|
|
|
|
->setType(PhabricatorMenuItemView::TYPE_LINK)
|
|
|
|
->setName($name)
|
|
|
|
->setHref($href);
|
|
|
|
|
2013-02-06 20:41:57 +01:00
|
|
|
if ($key !== null) {
|
2013-02-06 23:05:11 +01:00
|
|
|
$item->setKey($key);
|
2013-02-06 20:41:57 +01:00
|
|
|
}
|
2012-12-07 22:34:44 +01:00
|
|
|
|
|
|
|
$this->addMenuItem($item);
|
|
|
|
|
|
|
|
return $item;
|
|
|
|
}
|
|
|
|
|
2013-01-29 19:20:17 +01:00
|
|
|
public function newButton($name, $href) {
|
|
|
|
$item = id(new PhabricatorMenuItemView())
|
|
|
|
->setType(PhabricatorMenuItemView::TYPE_BUTTON)
|
|
|
|
->setName($name)
|
|
|
|
->setHref($href);
|
|
|
|
|
|
|
|
$this->addMenuItem($item);
|
|
|
|
|
|
|
|
return $item;
|
|
|
|
}
|
|
|
|
|
2012-12-07 22:32:14 +01:00
|
|
|
public function addMenuItem(PhabricatorMenuItemView $item) {
|
2013-02-03 19:02:35 +01:00
|
|
|
return $this->addMenuItemAfter(null, $item);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addMenuItemAfter($key, PhabricatorMenuItemView $item) {
|
|
|
|
if ($key === null) {
|
|
|
|
$this->items[] = $item;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$this->getItem($key)) {
|
|
|
|
throw new Exception("No such key '{$key}' to add menu item after!");
|
|
|
|
}
|
|
|
|
|
|
|
|
$result = array();
|
|
|
|
foreach ($this->items as $other) {
|
|
|
|
$result[] = $other;
|
|
|
|
if ($other->getKey() == $key) {
|
|
|
|
$result[] = $item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->items = $result;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addMenuItemBefore($key, PhabricatorMenuItemView $item) {
|
|
|
|
if ($key === null) {
|
|
|
|
array_unshift($this->items, $item);
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->requireKey($key);
|
|
|
|
|
|
|
|
$result = array();
|
|
|
|
foreach ($this->items as $other) {
|
|
|
|
if ($other->getKey() == $key) {
|
|
|
|
$result[] = $item;
|
|
|
|
}
|
|
|
|
$result[] = $other;
|
|
|
|
}
|
2012-12-07 22:32:14 +01:00
|
|
|
|
2013-02-03 19:02:35 +01:00
|
|
|
$this->items = $result;
|
2012-12-07 22:32:14 +01:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2013-02-03 19:02:35 +01:00
|
|
|
public function addMenuItemToLabel($key, PhabricatorMenuItemView $item) {
|
|
|
|
$this->requireKey($key);
|
|
|
|
|
|
|
|
$other = $this->getItem($key);
|
|
|
|
if ($other->getType() != PhabricatorMenuItemView::TYPE_LABEL) {
|
|
|
|
throw new Exception("Menu item '{$key}' is not a label!");
|
|
|
|
}
|
|
|
|
|
|
|
|
$seen = false;
|
|
|
|
$after = null;
|
|
|
|
foreach ($this->items as $other) {
|
|
|
|
if (!$seen) {
|
|
|
|
if ($other->getKey() == $key) {
|
|
|
|
$seen = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ($other->getType() == PhabricatorMenuItemView::TYPE_LABEL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$after = $other->getKey();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->addMenuItemAfter($after, $item);
|
|
|
|
}
|
|
|
|
|
|
|
|
private function requireKey($key) {
|
|
|
|
if (!$this->getItem($key)) {
|
|
|
|
throw new Exception("No menu item with key '{$key}' exists!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-07 22:32:14 +01:00
|
|
|
public function getItem($key) {
|
Modernize file uploads
Summary:
Modernizes file uploads. In particular:
- Adds a mobile menu, with an "Upload File" item.
- Adds crumbs to the list view, detail view and upload view.
- Adds "Upload File" action to crumbs.
- Moves upload file to a separate page.
- Removes the combined upload file + recent files page.
- Makes upload file use a normal file control by default (works on mobile).
- Home page, file list and file upload page are now global drop targets which accept files dropped anywhere on them. Dragging a file into the window shows a mask and an instructional message.
- User education on this is a little weak but I think that's a big can of worms?
- Fixes a bug where dropping multiple files into a Remarkup text area produced bad results (resolves T2190).
T879 is related, although it's specifically about Maniphest. I've declined to make global drop targets yet there because there are multiple drop targets on the page with different meanings. That UI needs updating in general.
@chad, do we have an "upload" icon (counterpart to "download")?
Test Plan: Uploaded files in Maniphest, Differential, Files, and from Home. Dragged and dropped multiple files into Differential. Used crumbs, mobile.
Reviewers: chad, btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2190
Differential Revision: https://secure.phabricator.com/D4200
2012-12-17 01:34:01 +01:00
|
|
|
$key = (string)$key;
|
|
|
|
|
|
|
|
// NOTE: We could optimize this, but need to update any map when items have
|
|
|
|
// their keys change. Since that's moderately complex, wait for a profile
|
|
|
|
// or use case.
|
|
|
|
|
|
|
|
foreach ($this->items as $item) {
|
|
|
|
if ($item->getKey() == $key) {
|
|
|
|
return $item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
2012-12-07 22:32:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function getItems() {
|
|
|
|
return $this->items;
|
|
|
|
}
|
|
|
|
|
2013-01-16 19:50:41 +01:00
|
|
|
protected function willRender() {
|
Modernize file uploads
Summary:
Modernizes file uploads. In particular:
- Adds a mobile menu, with an "Upload File" item.
- Adds crumbs to the list view, detail view and upload view.
- Adds "Upload File" action to crumbs.
- Moves upload file to a separate page.
- Removes the combined upload file + recent files page.
- Makes upload file use a normal file control by default (works on mobile).
- Home page, file list and file upload page are now global drop targets which accept files dropped anywhere on them. Dragging a file into the window shows a mask and an instructional message.
- User education on this is a little weak but I think that's a big can of worms?
- Fixes a bug where dropping multiple files into a Remarkup text area produced bad results (resolves T2190).
T879 is related, although it's specifically about Maniphest. I've declined to make global drop targets yet there because there are multiple drop targets on the page with different meanings. That UI needs updating in general.
@chad, do we have an "upload" icon (counterpart to "download")?
Test Plan: Uploaded files in Maniphest, Differential, Files, and from Home. Dragged and dropped multiple files into Differential. Used crumbs, mobile.
Reviewers: chad, btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T2190
Differential Revision: https://secure.phabricator.com/D4200
2012-12-17 01:34:01 +01:00
|
|
|
$key_map = array();
|
|
|
|
foreach ($this->items as $item) {
|
|
|
|
$key = $item->getKey();
|
|
|
|
if ($key !== null) {
|
|
|
|
if (isset($key_map[$key])) {
|
|
|
|
throw new Exception(
|
|
|
|
"Menu contains duplicate items with key '{$key}'!");
|
|
|
|
}
|
|
|
|
$key_map[$key] = $item;
|
|
|
|
}
|
|
|
|
}
|
2012-12-07 22:32:14 +01:00
|
|
|
}
|
|
|
|
|
2013-01-16 19:50:41 +01:00
|
|
|
protected function getTagAttributes() {
|
|
|
|
return array(
|
|
|
|
'class' => 'phabricator-menu-view',
|
|
|
|
);
|
|
|
|
}
|
2013-02-03 19:02:35 +01:00
|
|
|
|
|
|
|
protected function getTagContent() {
|
2013-02-11 23:43:25 +01:00
|
|
|
return $this->renderSingleView($this->items);
|
2013-02-03 19:02:35 +01:00
|
|
|
}
|
2012-12-07 22:32:14 +01:00
|
|
|
}
|