Page MenuHomePhabricator

D18805.diff
No OneTemporary

D18805.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -9,7 +9,7 @@
'names' => array(
'conpherence.pkg.css' => 'e68cf1fa',
'conpherence.pkg.js' => '15191c65',
- 'core.pkg.css' => 'fdb27ef9',
+ 'core.pkg.css' => '5be8063f',
'core.pkg.js' => '4c79d74f',
'darkconsole.pkg.js' => '1f9a31bc',
'differential.pkg.css' => '45951e9e',
@@ -135,14 +135,14 @@
'rsrc/css/phui/object-item/phui-oi-color.css' => 'cd2b9b77',
'rsrc/css/phui/object-item/phui-oi-drag-ui.css' => '08f4ccc3',
'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '9d9685d6',
- 'rsrc/css/phui/object-item/phui-oi-list-view.css' => 'bf094950',
+ 'rsrc/css/phui/object-item/phui-oi-list-view.css' => '73c5f5c4',
'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => 'a8beebea',
'rsrc/css/phui/phui-action-list.css' => 'f7f61a34',
'rsrc/css/phui/phui-action-panel.css' => 'b4798122',
'rsrc/css/phui/phui-badge.css' => '22c0cf4f',
'rsrc/css/phui/phui-basic-nav-view.css' => '98c11ab3',
'rsrc/css/phui/phui-big-info-view.css' => 'acc3492c',
- 'rsrc/css/phui/phui-box.css' => '9f3745fb',
+ 'rsrc/css/phui/phui-box.css' => '4bd6cdb9',
'rsrc/css/phui/phui-chart.css' => '6bf6f78e',
'rsrc/css/phui/phui-cms.css' => '504b4b23',
'rsrc/css/phui/phui-comment-form.css' => 'ac68149f',
@@ -523,6 +523,7 @@
'rsrc/js/core/phtize.js' => 'd254d646',
'rsrc/js/phui/behavior-phui-dropdown-menu.js' => 'b95d6f7d',
'rsrc/js/phui/behavior-phui-file-upload.js' => 'b003d4fb',
+ 'rsrc/js/phui/behavior-phui-selectable-list.js' => '464259a2',
'rsrc/js/phui/behavior-phui-submenu.js' => 'a6f7a73b',
'rsrc/js/phui/behavior-phui-tab-group.js' => '0a0b10e9',
'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8',
@@ -673,6 +674,7 @@
'javelin-behavior-phui-dropdown-menu' => 'b95d6f7d',
'javelin-behavior-phui-file-upload' => 'b003d4fb',
'javelin-behavior-phui-hovercards' => 'bcaccd64',
+ 'javelin-behavior-phui-selectable-list' => '464259a2',
'javelin-behavior-phui-submenu' => 'a6f7a73b',
'javelin-behavior-phui-tab-group' => '0a0b10e9',
'javelin-behavior-phuix-example' => '68af71ca',
@@ -820,7 +822,7 @@
'phui-badge-view-css' => '22c0cf4f',
'phui-basic-nav-view-css' => '98c11ab3',
'phui-big-info-view-css' => 'acc3492c',
- 'phui-box-css' => '9f3745fb',
+ 'phui-box-css' => '4bd6cdb9',
'phui-button-bar-css' => 'f1ff5494',
'phui-button-css' => '1863cc6e',
'phui-button-simple-css' => '8e1baf68',
@@ -860,7 +862,7 @@
'phui-oi-color-css' => 'cd2b9b77',
'phui-oi-drag-ui-css' => '08f4ccc3',
'phui-oi-flush-ui-css' => '9d9685d6',
- 'phui-oi-list-view-css' => 'bf094950',
+ 'phui-oi-list-view-css' => '73c5f5c4',
'phui-oi-simple-ui-css' => 'a8beebea',
'phui-pager-css' => 'edcbc226',
'phui-pinboard-view-css' => '2495140e',
@@ -1226,6 +1228,11 @@
'javelin-behavior',
'javelin-dom',
),
+ '464259a2' => array(
+ 'javelin-behavior',
+ 'javelin-stratcom',
+ 'javelin-dom',
+ ),
'469c0d9e' => array(
'javelin-behavior',
'javelin-dom',
diff --git a/src/applications/maniphest/controller/ManiphestBatchEditController.php b/src/applications/maniphest/controller/ManiphestBatchEditController.php
--- a/src/applications/maniphest/controller/ManiphestBatchEditController.php
+++ b/src/applications/maniphest/controller/ManiphestBatchEditController.php
@@ -89,12 +89,7 @@
->setURI($job->getMonitorURI());
}
- $handles = ManiphestTaskListView::loadTaskHandles($viewer, $tasks);
-
- $list = new ManiphestTaskListView();
- $list->setTasks($tasks);
- $list->setUser($viewer);
- $list->setHandles($handles);
+ $list = $this->newBulkObjectList($tasks);
$template = new AphrontTokenizerTemplateView();
$template = $template->render();
@@ -142,21 +137,8 @@
'statusMap' => ManiphestTaskStatus::getTaskStatusMap(),
));
- $form = id(new AphrontFormView())
- ->setUser($viewer)
- ->addHiddenInput('board', $board_id)
- ->setID('maniphest-batch-edit-form');
-
- foreach ($tasks as $task) {
- $form->appendChild(
- phutil_tag(
- 'input',
- array(
- 'type' => 'hidden',
- 'name' => 'batch[]',
- 'value' => $task->getID(),
- )));
- }
+ $form = id(new PHUIFormLayoutView())
+ ->setUser($viewer);
$form->appendChild(
phutil_tag(
@@ -166,6 +148,7 @@
'name' => 'actions',
'id' => 'batch-form-actions',
)));
+
$form->appendChild(
id(new PHUIFormInsetView())
->setTitle(pht('Actions'))
@@ -210,17 +193,63 @@
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setForm($form);
- $view = id(new PHUITwoColumnView())
- ->setHeader($header)
- ->setFooter(array(
+
+ $complete_form = phabricator_form(
+ $viewer,
+ array(
+ 'action' => $request->getRequestURI(),
+ 'method' => 'POST',
+ 'id' => 'maniphest-batch-edit-form',
+ ),
+ array(
+ phutil_tag(
+ 'input',
+ array(
+ 'type' => 'hidden',
+ 'name' => 'board',
+ 'value' => $board_id,
+ )),
$task_box,
$form_box,
));
+ $view = id(new PHUITwoColumnView())
+ ->setHeader($header)
+ ->setFooter($complete_form);
+
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
+ private function newBulkObjectList(array $objects) {
+ $viewer = $this->getViewer();
+ $objects = mpull($objects, null, 'getPHID');
+
+ $handles = $viewer->loadHandles(array_keys($objects));
+
+ $status_closed = PhabricatorObjectHandle::STATUS_CLOSED;
+
+ $list = id(new PHUIObjectItemListView())
+ ->setViewer($viewer)
+ ->setFlush(true);
+
+ foreach ($objects as $phid => $object) {
+ $handle = $handles[$phid];
+
+ $is_closed = ($handle->getStatus() === $status_closed);
+
+ $item = id(new PHUIObjectItemView())
+ ->setHeader($handle->getFullName())
+ ->setHref($handle->getURI())
+ ->setDisabled($is_closed)
+ ->setSelectable('batch[]', $object->getID(), true);
+
+ $list->addItem($item);
+ }
+
+ return $list;
+ }
+
}
diff --git a/src/view/phui/PHUIObjectItemView.php b/src/view/phui/PHUIObjectItemView.php
--- a/src/view/phui/PHUIObjectItemView.php
+++ b/src/view/phui/PHUIObjectItemView.php
@@ -29,6 +29,10 @@
private $coverImage;
private $description;
+ private $selectableName;
+ private $selectableValue;
+ private $isSelected;
+
public function setDisabled($disabled) {
$this->disabled = $disabled;
return $this;
@@ -160,6 +164,13 @@
return $this;
}
+ public function setSelectable($name, $value, $is_selected) {
+ $this->selectableName = $name;
+ $this->selectableValue = $value;
+ $this->isSelected = $is_selected;
+ return $this;
+ }
+
public function setEpoch($epoch) {
$date = phabricator_datetime($epoch, $this->getUser());
$this->addIcon('none', $date);
@@ -239,6 +250,8 @@
}
protected function getTagAttributes() {
+ $sigils = array();
+
$item_classes = array();
$item_classes[] = 'phui-oi';
@@ -286,6 +299,17 @@
throw new Exception(pht('Invalid effect!'));
}
+ if ($this->isSelected) {
+ $item_classes[] = 'phui-oi-selected';
+ }
+
+ if ($this->selectableName !== null) {
+ $item_classes[] = 'phui-oi-selectable';
+ $sigils[] = 'phui-oi-selectable';
+
+ Javelin::initBehavior('phui-selectable-list');
+ }
+
if ($this->getGrippable()) {
$item_classes[] = 'phui-oi-grippable';
}
@@ -300,6 +324,7 @@
return array(
'class' => $item_classes,
+ 'sigil' => $sigils,
);
}
@@ -628,6 +653,24 @@
$countdown);
}
+ if ($this->selectableName !== null) {
+ $checkbox = phutil_tag(
+ 'input',
+ array(
+ 'type' => 'checkbox',
+ 'name' => $this->selectableName,
+ 'value' => $this->selectableValue,
+ 'checked' => ($this->isSelected ? 'checked' : null),
+ ));
+
+ $column0 = phutil_tag(
+ 'div',
+ array(
+ 'class' => 'phui-oi-col0 phui-oi-checkbox',
+ ),
+ $checkbox);
+ }
+
$column1 = phutil_tag(
'div',
array(
diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css b/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css
--- a/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css
+++ b/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css
@@ -664,3 +664,22 @@
padding: 0 8px 8px;
text-align: left;
}
+
+.phui-oi-col0.phui-oi-checkbox {
+ width: 28px;
+ text-align: center;
+}
+
+.phui-oi-selectable {
+ cursor: pointer;
+ user-select: none;
+ -webkit-user-select: none;
+}
+
+/* When the list selection state can be toggled on the client (as in the bulk
+ editor), keep the border color consistent to make the interaction feel more
+ robust. */
+ul.phui-oi-list-view .phui-oi-selectable
+ .phui-oi-frame {
+ border-color: {$blueborder};
+}
diff --git a/webroot/rsrc/css/phui/phui-box.css b/webroot/rsrc/css/phui/phui-box.css
--- a/webroot/rsrc/css/phui/phui-box.css
+++ b/webroot/rsrc/css/phui/phui-box.css
@@ -103,6 +103,10 @@
padding: 2px 8px;
}
+.phui-box-blue-property .phui-oi-list-view.phui-oi-list-flush {
+ padding: 0;
+}
+
body .phui-box-blue-property.phui-object-box.phui-object-box-collapsed {
padding: 0;
}
diff --git a/webroot/rsrc/js/phui/behavior-phui-selectable-list.js b/webroot/rsrc/js/phui/behavior-phui-selectable-list.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/phui/behavior-phui-selectable-list.js
@@ -0,0 +1,44 @@
+/**
+ * @provides javelin-behavior-phui-selectable-list
+ * @requires javelin-behavior
+ * javelin-stratcom
+ * javelin-dom
+ */
+
+JX.behavior('phui-selectable-list', function() {
+
+ JX.Stratcom.listen('click', 'phui-oi-selectable', function(e) {
+ if (!e.isNormalClick()) {
+ return;
+ }
+
+ // If the user clicked a link, ignore it.
+ if (e.getNode('tag:a')) {
+ return;
+ }
+
+ var root = e.getNode('phui-oi-selectable');
+
+ // If the user did not click the checkbox, pretend they did. This makes
+ // the entire element a click target to make changing the selection set a
+ // bit easier.
+ if (!e.getNode('tag:input')) {
+ var checkbox = getCheckbox(root);
+ checkbox.checked = !checkbox.checked;
+
+ e.kill();
+ }
+
+ setTimeout(JX.bind(null, redraw, root), 0);
+ });
+
+ function getCheckbox(root) {
+ return JX.DOM.find(root, 'input');
+ }
+
+ function redraw(root) {
+ var checkbox = getCheckbox(root);
+ JX.DOM.alterClass(root, 'phui-oi-selected', !!checkbox.checked);
+ }
+
+});

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 13, 6:03 PM (3 d, 16 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6729187
Default Alt Text
D18805.diff (10 KB)

Event Timeline