Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F18749527
D18863.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
32 KB
Referenced Files
None
Subscribers
None
D18863.diff
View Options
diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -81,7 +81,6 @@
'rsrc/css/application/harbormaster/harbormaster.css' => 'f491c9f4',
'rsrc/css/application/herald/herald-test.css' => 'a52e323e',
'rsrc/css/application/herald/herald.css' => 'cd8d0134',
- 'rsrc/css/application/maniphest/batch-editor.css' => 'b0f0b6d5',
'rsrc/css/application/maniphest/report.css' => '9b9580b7',
'rsrc/css/application/maniphest/task-edit.css' => 'fda62a9b',
'rsrc/css/application/maniphest/task-summary.css' => '11cc5344',
@@ -143,6 +142,7 @@
'rsrc/css/phui/phui-basic-nav-view.css' => '98c11ab3',
'rsrc/css/phui/phui-big-info-view.css' => 'acc3492c',
'rsrc/css/phui/phui-box.css' => '4bd6cdb9',
+ 'rsrc/css/phui/phui-bulk-editor.css' => '1fe728a8',
'rsrc/css/phui/phui-chart.css' => '6bf6f78e',
'rsrc/css/phui/phui-cms.css' => '504b4b23',
'rsrc/css/phui/phui-comment-form.css' => 'ac68149f',
@@ -419,7 +419,6 @@
'rsrc/js/application/herald/HeraldRuleEditor.js' => '2dff5579',
'rsrc/js/application/herald/PathTypeahead.js' => 'f7fc67ec',
'rsrc/js/application/herald/herald-rule-editor.js' => '7ebaeed3',
- 'rsrc/js/application/maniphest/behavior-batch-editor.js' => '782ab6e7',
'rsrc/js/application/maniphest/behavior-batch-selector.js' => 'ad54037e',
'rsrc/js/application/maniphest/behavior-line-chart.js' => 'e4232876',
'rsrc/js/application/maniphest/behavior-list-edit.js' => 'a9f88de2',
@@ -477,6 +476,7 @@
'rsrc/js/core/behavior-audio-source.js' => '59b251eb',
'rsrc/js/core/behavior-autofocus.js' => '7319e029',
'rsrc/js/core/behavior-badge-view.js' => '8ff5e24c',
+ 'rsrc/js/core/behavior-bulk-editor.js' => '5e178556',
'rsrc/js/core/behavior-choose-control.js' => '327a00d1',
'rsrc/js/core/behavior-copy.js' => 'b0b8f86d',
'rsrc/js/core/behavior-detect-timezone.js' => '4c193c96',
@@ -532,7 +532,7 @@
'rsrc/js/phuix/PHUIXButtonView.js' => '8a91e1ac',
'rsrc/js/phuix/PHUIXDropdownMenu.js' => '04b2ae03',
'rsrc/js/phuix/PHUIXExample.js' => '68af71ca',
- 'rsrc/js/phuix/PHUIXFormControl.js' => '83e03671',
+ 'rsrc/js/phuix/PHUIXFormControl.js' => '68bb05aa',
'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b',
),
'symbols' => array(
@@ -595,6 +595,7 @@
'javelin-behavior-audio-source' => '59b251eb',
'javelin-behavior-audit-preview' => 'd835b03a',
'javelin-behavior-badge-view' => '8ff5e24c',
+ 'javelin-behavior-bulk-editor' => '5e178556',
'javelin-behavior-bulk-job-reload' => 'edf8a145',
'javelin-behavior-calendar-month-view' => 'fe33e256',
'javelin-behavior-choose-control' => '327a00d1',
@@ -642,7 +643,6 @@
'javelin-behavior-lightbox-attachments' => '560f41da',
'javelin-behavior-line-chart' => 'e4232876',
'javelin-behavior-load-blame' => '42126667',
- 'javelin-behavior-maniphest-batch-editor' => '782ab6e7',
'javelin-behavior-maniphest-batch-selector' => 'ad54037e',
'javelin-behavior-maniphest-list-editor' => 'a9f88de2',
'javelin-behavior-maniphest-subpriority-editor' => '71237763',
@@ -756,7 +756,6 @@
'javelin-workboard-column' => '758b4758',
'javelin-workboard-controller' => '26167537',
'javelin-workflow' => '1e911d0f',
- 'maniphest-batch-editor' => 'b0f0b6d5',
'maniphest-report-css' => '9b9580b7',
'maniphest-task-edit-css' => 'fda62a9b',
'maniphest-task-summary-css' => '11cc5344',
@@ -823,6 +822,7 @@
'phui-basic-nav-view-css' => '98c11ab3',
'phui-big-info-view-css' => 'acc3492c',
'phui-box-css' => '4bd6cdb9',
+ 'phui-bulk-editor-css' => '1fe728a8',
'phui-button-bar-css' => 'f1ff5494',
'phui-button-css' => '1863cc6e',
'phui-button-simple-css' => '8e1baf68',
@@ -884,7 +884,7 @@
'phuix-autocomplete' => 'e0731603',
'phuix-button-view' => '8a91e1ac',
'phuix-dropdown-menu' => '04b2ae03',
- 'phuix-form-control-view' => '83e03671',
+ 'phuix-form-control-view' => '68bb05aa',
'phuix-icon-view' => 'bff6884b',
'policy-css' => '957ea14c',
'policy-edit-css' => '815c66f7',
@@ -1387,6 +1387,15 @@
'javelin-stratcom',
'javelin-dom',
),
+ '5e178556' => array(
+ 'javelin-behavior',
+ 'javelin-dom',
+ 'javelin-util',
+ 'phabricator-prefab',
+ 'multirow-row-manager',
+ 'javelin-json',
+ 'phuix-form-control-view',
+ ),
'5e2634b9' => array(
'javelin-behavior',
'javelin-aphlict',
@@ -1436,6 +1445,10 @@
'javelin-dom',
'phuix-button-view',
),
+ '68bb05aa' => array(
+ 'javelin-install',
+ 'javelin-dom',
+ ),
'69adf288' => array(
'javelin-install',
),
@@ -1524,14 +1537,6 @@
'javelin-request',
'javelin-util',
),
- '782ab6e7' => array(
- 'javelin-behavior',
- 'javelin-dom',
- 'javelin-util',
- 'phabricator-prefab',
- 'multirow-row-manager',
- 'javelin-json',
- ),
'7927a7d3' => array(
'javelin-behavior',
'javelin-quicksand',
@@ -1570,10 +1575,6 @@
'javelin-behavior',
'javelin-scrollbar',
),
- '83e03671' => array(
- 'javelin-install',
- 'javelin-dom',
- ),
'8499b6ab' => array(
'javelin-behavior',
'javelin-dom',
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -222,6 +222,8 @@
'AuditConduitAPIMethod' => 'applications/audit/conduit/AuditConduitAPIMethod.php',
'AuditQueryConduitAPIMethod' => 'applications/audit/conduit/AuditQueryConduitAPIMethod.php',
'AuthManageProvidersCapability' => 'applications/auth/capability/AuthManageProvidersCapability.php',
+ 'BulkParameterType' => 'applications/transactions/bulk/type/BulkParameterType.php',
+ 'BulkStringParameterType' => 'applications/transactions/bulk/type/BulkStringParameterType.php',
'CalendarTimeUtil' => 'applications/calendar/util/CalendarTimeUtil.php',
'CalendarTimeUtilTestCase' => 'applications/calendar/__tests__/CalendarTimeUtilTestCase.php',
'CelerityAPI' => 'applications/celerity/CelerityAPI.php',
@@ -5242,6 +5244,8 @@
'AuditConduitAPIMethod' => 'ConduitAPIMethod',
'AuditQueryConduitAPIMethod' => 'AuditConduitAPIMethod',
'AuthManageProvidersCapability' => 'PhabricatorPolicyCapability',
+ 'BulkParameterType' => 'Phobject',
+ 'BulkStringParameterType' => 'BulkParameterType',
'CalendarTimeUtil' => 'Phobject',
'CalendarTimeUtilTestCase' => 'PhabricatorTestCase',
'CelerityAPI' => 'Phobject',
diff --git a/src/applications/maniphest/bulk/ManiphestTaskBulkEngine.php b/src/applications/maniphest/bulk/ManiphestTaskBulkEngine.php
--- a/src/applications/maniphest/bulk/ManiphestTaskBulkEngine.php
+++ b/src/applications/maniphest/bulk/ManiphestTaskBulkEngine.php
@@ -18,6 +18,10 @@
return new ManiphestTaskSearchEngine();
}
+ public function newEditEngine() {
+ return new ManiphestEditEngine();
+ }
+
public function getDoneURI() {
$board_uri = $this->getBoardURI();
if ($board_uri) {
diff --git a/src/applications/maniphest/editor/ManiphestEditEngine.php b/src/applications/maniphest/editor/ManiphestEditEngine.php
--- a/src/applications/maniphest/editor/ManiphestEditEngine.php
+++ b/src/applications/maniphest/editor/ManiphestEditEngine.php
@@ -178,6 +178,7 @@
id(new PhabricatorTextEditField())
->setKey('title')
->setLabel(pht('Title'))
+ ->setBulkEditLabel(pht('Set title to'))
->setDescription(pht('Name of the task.'))
->setConduitDescription(pht('Rename the task.'))
->setConduitTypeDescription(pht('New task name.'))
diff --git a/src/applications/transactions/bulk/PhabricatorBulkEngine.php b/src/applications/transactions/bulk/PhabricatorBulkEngine.php
--- a/src/applications/transactions/bulk/PhabricatorBulkEngine.php
+++ b/src/applications/transactions/bulk/PhabricatorBulkEngine.php
@@ -10,7 +10,10 @@
private $editableList;
private $targetList;
+ private $rootFormID;
+
abstract public function newSearchEngine();
+ abstract public function newEditEngine();
public function getCancelURI() {
$saved_query = $this->savedQuery;
@@ -118,7 +121,7 @@
array(
'action' => $this->getBulkURI(),
'method' => 'POST',
- 'id' => 'maniphest-batch-edit-form',
+ 'id' => $this->getRootFormID(),
),
array(
$this->newContextInputs(),
@@ -290,95 +293,60 @@
private function newBulkActionForm() {
$viewer = $this->getViewer();
+ $input_id = celerity_generate_unique_node_id();
- $cancel_uri = $this->getCancelURI();
-
- $template = new AphrontTokenizerTemplateView();
- $template = $template->render();
-
- $projects_source = new PhabricatorProjectDatasource();
- $mailable_source = new PhabricatorMetaMTAMailableDatasource();
- $mailable_source->setViewer($viewer);
- $owner_source = new ManiphestAssigneeDatasource();
- $owner_source->setViewer($viewer);
- $spaces_source = id(new PhabricatorSpacesNamespaceDatasource())
+ $edit_engine = id($this->newEditEngine())
->setViewer($viewer);
- require_celerity_resource('maniphest-batch-editor');
+ $edit_map = $edit_engine->newBulkEditMap();
+
+ require_celerity_resource('phui-bulk-editor-css');
Javelin::initBehavior(
- 'maniphest-batch-editor',
+ 'bulk-editor',
array(
- 'root' => 'maniphest-batch-edit-form',
- 'tokenizerTemplate' => $template,
- 'sources' => array(
- 'project' => array(
- 'src' => $projects_source->getDatasourceURI(),
- 'placeholder' => $projects_source->getPlaceholderText(),
- 'browseURI' => $projects_source->getBrowseURI(),
- ),
- 'owner' => array(
- 'src' => $owner_source->getDatasourceURI(),
- 'placeholder' => $owner_source->getPlaceholderText(),
- 'browseURI' => $owner_source->getBrowseURI(),
- 'limit' => 1,
- ),
- 'cc' => array(
- 'src' => $mailable_source->getDatasourceURI(),
- 'placeholder' => $mailable_source->getPlaceholderText(),
- 'browseURI' => $mailable_source->getBrowseURI(),
- ),
- 'spaces' => array(
- 'src' => $spaces_source->getDatasourceURI(),
- 'placeholder' => $spaces_source->getPlaceholderText(),
- 'browseURI' => $spaces_source->getBrowseURI(),
- 'limit' => 1,
- ),
- ),
- 'input' => 'batch-form-actions',
- 'priorityMap' => ManiphestTaskPriority::getTaskPriorityMap(),
- 'statusMap' => ManiphestTaskStatus::getTaskStatusMap(),
+ 'rootNodeID' => $this->getRootFormID(),
+ 'inputNodeID' => $input_id,
+ 'edits' => $edit_map,
));
- $form = id(new PHUIFormLayoutView())
- ->setUser($viewer);
+ $cancel_uri = $this->getCancelURI();
- $form->appendChild(
- phutil_tag(
- 'input',
- array(
- 'type' => 'hidden',
- 'name' => 'actions',
- 'id' => 'batch-form-actions',
- )));
-
- $form->appendChild(
- id(new PHUIFormInsetView())
- ->setTitle(pht('Bulk Edit Actions'))
- ->setRightButton(
- javelin_tag(
- 'a',
- array(
- 'href' => '#',
- 'class' => 'button button-green',
- 'sigil' => 'add-action',
- 'mustcapture' => true,
- ),
- pht('Add Another Action')))
- ->setContent(
- javelin_tag(
- 'table',
- array(
- 'sigil' => 'maniphest-batch-actions',
- 'class' => 'maniphest-batch-actions-table',
- ),
- '')))
+ return id(new PHUIFormLayoutView())
+ ->setViewer($viewer)
+ ->appendChild(
+ phutil_tag(
+ 'input',
+ array(
+ 'type' => 'hidden',
+ 'name' => 'xactions',
+ 'id' => $input_id,
+ )))
+ ->appendChild(
+ id(new PHUIFormInsetView())
+ ->setTitle(pht('Bulk Edit Actions'))
+ ->setRightButton(
+ javelin_tag(
+ 'a',
+ array(
+ 'href' => '#',
+ 'class' => 'button button-green',
+ 'sigil' => 'add-action',
+ 'mustcapture' => true,
+ ),
+ pht('Add Another Action')))
+ ->setContent(
+ javelin_tag(
+ 'table',
+ array(
+ 'sigil' => 'bulk-actions',
+ 'class' => 'bulk-edit-table',
+ ),
+ '')))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Apply Bulk Edit'))
->addCancelButton($cancel_uri));
-
- return $form;
}
private function buildEditResponse() {
@@ -405,31 +373,33 @@
'You have not selected any objects to edit.'));
}
- $raw_actions = $request->getStr('actions');
- if ($raw_actions) {
- $actions = phutil_json_decode($raw_actions);
+ $raw_xactions = $request->getStr('xactions');
+ if ($raw_xactions) {
+ $raw_xactions = phutil_json_decode($raw_xactions);
} else {
- $actions = array();
+ $raw_xactions = array();
}
- if (!$actions) {
+ if (!$raw_xactions) {
throw new Exception(
pht(
'You have not chosen any edits to apply.'));
}
+ $edit_engine = id($this->newEditEngine())
+ ->setViewer($viewer);
+
+ $xactions = $edit_engine->newRawBulkTransactions($raw_xactions);
+
$cancel_uri = $this->getCancelURI();
$done_uri = $this->getDoneURI();
$job = PhabricatorWorkerBulkJob::initializeNewJob(
$viewer,
- // TODO: This is a Maniphest-specific job type for now, but will become
- // a generic one so it gets to live here for now instead of in the task
- // specific BulkEngine subclass.
- new ManiphestTaskEditBulkJobType(),
+ new PhabricatorEditEngineBulkJobType(),
array(
- 'taskPHIDs' => mpull($objects, 'getPHID'),
- 'actions' => $actions,
+ 'objectPHIDs' => mpull($objects, 'getPHID'),
+ 'xactions' => $xactions,
'cancelURI' => $cancel_uri,
'doneURI' => $done_uri,
));
@@ -451,4 +421,12 @@
->setURI($job->getMonitorURI());
}
+ private function getRootFormID() {
+ if (!$this->rootFormID) {
+ $this->rootFormID = celerity_generate_unique_node_id();
+ }
+
+ return $this->rootFormID;
+ }
+
}
diff --git a/src/applications/transactions/bulk/type/BulkParameterType.php b/src/applications/transactions/bulk/type/BulkParameterType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/bulk/type/BulkParameterType.php
@@ -0,0 +1,24 @@
+<?php
+
+abstract class BulkParameterType extends Phobject {
+
+ private $viewer;
+
+ final public function setViewer(PhabricatorUser $viewer) {
+ $this->viewer = $viewer;
+ return $this;
+ }
+
+ final public function getViewer() {
+ return $this->viewer;
+ }
+
+ abstract public function getPHUIXControlType();
+
+ public function getPHUIXControlSpecification() {
+ return array(
+ 'value' => null,
+ );
+ }
+
+}
diff --git a/src/applications/transactions/bulk/type/BulkStringParameterType.php b/src/applications/transactions/bulk/type/BulkStringParameterType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/bulk/type/BulkStringParameterType.php
@@ -0,0 +1,10 @@
+<?php
+
+final class BulkStringParameterType
+ extends BulkParameterType {
+
+ public function getPHUIXControlType() {
+ return 'text';
+ }
+
+}
diff --git a/src/applications/transactions/editengine/PhabricatorEditEngine.php b/src/applications/transactions/editengine/PhabricatorEditEngine.php
--- a/src/applications/transactions/editengine/PhabricatorEditEngine.php
+++ b/src/applications/transactions/editengine/PhabricatorEditEngine.php
@@ -2421,6 +2421,71 @@
}
+/* -( Bulk Edits )--------------------------------------------------------- */
+
+
+ final public function newBulkEditMap() {
+ $config = $this->loadDefaultConfiguration();
+ if (!$config) {
+ throw new Exception(
+ pht('No default edit engine configuration for bulk edit.'));
+ }
+
+ $object = $this->newEditableObject();
+ $fields = $this->buildEditFields($object);
+
+ $edit_types = $this->getBulkEditTypesFromFields($fields);
+
+ $map = array();
+ foreach ($edit_types as $key => $type) {
+ $bulk_type = $type->getBulkParameterType();
+ if ($bulk_type === null) {
+ continue;
+ }
+
+ $bulk_label = $type->getBulkEditLabel();
+ if ($bulk_label === null) {
+ continue;
+ }
+
+ $map[] = array(
+ 'label' => $bulk_label,
+ 'xaction' => $type->getTransactionType(),
+ 'control' => array(
+ 'type' => $bulk_type->getPHUIXControlType(),
+ 'spec' => (object)$bulk_type->getPHUIXControlSpecification(),
+ ),
+ );
+ }
+
+ return $map;
+ }
+
+
+ final public function newRawBulkTransactions(array $xactions) {
+ return $xactions;
+ }
+
+ private function getBulkEditTypesFromFields(array $fields) {
+ $types = array();
+
+ foreach ($fields as $field) {
+ $field_types = $field->getBulkEditTypes();
+
+ if ($field_types === null) {
+ continue;
+ }
+
+ foreach ($field_types as $field_type) {
+ $field_type->setField($field);
+ $types[$field_type->getEditType()] = $field_type;
+ }
+ }
+
+ return $types;
+ }
+
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
diff --git a/src/applications/transactions/editfield/PhabricatorEditField.php b/src/applications/transactions/editfield/PhabricatorEditField.php
--- a/src/applications/transactions/editfield/PhabricatorEditField.php
+++ b/src/applications/transactions/editfield/PhabricatorEditField.php
@@ -17,6 +17,7 @@
private $previewPanel;
private $controlID;
private $controlInstructions;
+ private $bulkEditLabel;
private $description;
private $conduitDescription;
@@ -45,6 +46,7 @@
private $isConduitOnly = false;
private $conduitEditTypes;
+ private $bulkEditTypes;
public function setKey($key) {
$this->key = $key;
@@ -64,6 +66,15 @@
return $this->label;
}
+ public function setBulkEditLabel($bulk_edit_label) {
+ $this->bulkEditLabel = $bulk_edit_label;
+ return $this;
+ }
+
+ public function getBulkEditLabel() {
+ return $this->bulkEditLabel;
+ }
+
public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;
@@ -625,6 +636,22 @@
return new AphrontStringHTTPParameterType();
}
+ protected function getBulkParameterType() {
+ $type = $this->newBulkParameterType();
+
+ if (!$type) {
+ return null;
+ }
+
+ $type->setViewer($this->getViewer());
+
+ return $type;
+ }
+
+ protected function newBulkParameterType() {
+ return null;
+ }
+
public function getConduitParameterType() {
$type = $this->newConduitParameterType();
@@ -657,8 +684,15 @@
return null;
}
- return id(new PhabricatorSimpleEditType())
+ $edit_type = id(new PhabricatorSimpleEditType())
->setConduitParameterType($parameter_type);
+
+ $bulk_type = $this->getBulkParameterType();
+ if ($bulk_type) {
+ $edit_type->setBulkParameterType($bulk_type);
+ }
+
+ return $edit_type;
}
protected function getEditType() {
@@ -718,6 +752,31 @@
return array($edit_type);
}
+ final public function getBulkEditTypes() {
+ if ($this->bulkEditTypes === null) {
+ $edit_types = $this->newBulkEditTypes();
+ $edit_types = mpull($edit_types, null, 'getEditType');
+
+ foreach ($edit_types as $edit_type) {
+ $edit_type->setEditField($this);
+ }
+
+ $this->bulkEditTypes = $edit_types;
+ }
+
+ return $this->bulkEditTypes;
+ }
+
+ protected function newBulkEditTypes() {
+ $edit_type = $this->getEditType();
+
+ if (!$edit_type) {
+ return array();
+ }
+
+ return array($edit_type);
+ }
+
public function getCommentAction() {
$label = $this->getCommentActionLabel();
if ($label === null) {
diff --git a/src/applications/transactions/editfield/PhabricatorPHIDListEditField.php b/src/applications/transactions/editfield/PhabricatorPHIDListEditField.php
--- a/src/applications/transactions/editfield/PhabricatorPHIDListEditField.php
+++ b/src/applications/transactions/editfield/PhabricatorPHIDListEditField.php
@@ -104,6 +104,10 @@
return $type;
}
+ protected function newBulkEditTypes() {
+ return $this->newConduitEditTypes();
+ }
+
protected function newConduitEditTypes() {
if (!$this->getUseEdgeTransactions()) {
return parent::newConduitEditTypes();
diff --git a/src/applications/transactions/editfield/PhabricatorTextEditField.php b/src/applications/transactions/editfield/PhabricatorTextEditField.php
--- a/src/applications/transactions/editfield/PhabricatorTextEditField.php
+++ b/src/applications/transactions/editfield/PhabricatorTextEditField.php
@@ -29,4 +29,8 @@
return new ConduitStringParameterType();
}
+ protected function newBulkParameterType() {
+ return new BulkStringParameterType();
+ }
+
}
diff --git a/src/applications/transactions/edittype/PhabricatorEditType.php b/src/applications/transactions/edittype/PhabricatorEditType.php
--- a/src/applications/transactions/edittype/PhabricatorEditType.php
+++ b/src/applications/transactions/edittype/PhabricatorEditType.php
@@ -14,6 +14,9 @@
private $conduitTypeDescription;
private $conduitParameterType;
+ private $bulkParameterType;
+ private $bulkEditLabel;
+
public function setLabel($label) {
$this->label = $label;
return $this;
@@ -23,6 +26,19 @@
return $this->label;
}
+ public function setBulkEditLabel($bulk_edit_label) {
+ $this->bulkEditLabel = $bulk_edit_label;
+ return $this;
+ }
+
+ public function getBulkEditLabel() {
+ if ($this->bulkEditLabel !== null) {
+ return $this->bulkEditLabel;
+ }
+
+ return $this->getField()->getBulkEditLabel();
+ }
+
public function setField(PhabricatorEditField $field) {
$this->field = $field;
return $this;
@@ -85,6 +101,30 @@
return $this->editField;
}
+
+/* -( Bulk )--------------------------------------------------------------- */
+
+
+ protected function newBulkParameterType() {
+ if ($this->bulkParameterType) {
+ return clone $this->bulkParameterType;
+ }
+
+ return null;
+ }
+
+
+ public function setBulkParameterType(BulkParameterType $type) {
+ $this->bulkParameterType = $type;
+ return $this;
+ }
+
+
+ public function getBulkParameterType() {
+ return $this->newBulkParameterType();
+ }
+
+
/* -( Conduit )------------------------------------------------------------ */
diff --git a/webroot/rsrc/css/application/maniphest/batch-editor.css b/webroot/rsrc/css/application/maniphest/batch-editor.css
deleted file mode 100644
--- a/webroot/rsrc/css/application/maniphest/batch-editor.css
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * @provides maniphest-batch-editor
- */
-.maniphest-batch-actions-table {
- width: 100%;
- margin: 12px 0;
-}
-
-.maniphest-batch-actions-table td {
- padding: 4px 8px;
- vertical-align: middle;
-}
-
-.batch-editor-input {
- width: 100%;
- text-align: left;
-}
diff --git a/webroot/rsrc/css/phui/phui-bulk-editor.css b/webroot/rsrc/css/phui/phui-bulk-editor.css
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/css/phui/phui-bulk-editor.css
@@ -0,0 +1,22 @@
+/**
+ * @provides phui-bulk-editor-css
+ */
+
+.bulk-edit-table {
+ width: 100%;
+ margin: 12px 0;
+}
+
+.bulk-edit-table td {
+ padding: 4px 8px;
+ vertical-align: middle;
+}
+
+.bulk-edit-input {
+ width: 100%;
+ text-align: left;
+}
+
+.bulk-edit-input input {
+ width: 100%;
+}
diff --git a/webroot/rsrc/js/application/maniphest/behavior-batch-editor.js b/webroot/rsrc/js/application/maniphest/behavior-batch-editor.js
deleted file mode 100644
--- a/webroot/rsrc/js/application/maniphest/behavior-batch-editor.js
+++ /dev/null
@@ -1,158 +0,0 @@
-/**
- * @provides javelin-behavior-maniphest-batch-editor
- * @requires javelin-behavior
- * javelin-dom
- * javelin-util
- * phabricator-prefab
- * multirow-row-manager
- * javelin-json
- */
-
-JX.behavior('maniphest-batch-editor', function(config) {
- var root = JX.$(config.root);
- var editor_table = JX.DOM.find(root, 'table', 'maniphest-batch-actions');
- var manager = new JX.MultirowRowManager(editor_table);
- var action_rows = [];
-
- function renderRow() {
- var action_select = JX.Prefab.renderSelect(
- {
- 'add_project': 'Add Projects',
- 'remove_project' : 'Remove Projects',
- 'priority': 'Change Priority',
- 'status': 'Change Status',
- 'add_comment': 'Comment',
- 'assign': 'Assign',
- 'add_ccs' : 'Add CCs',
- 'remove_ccs' : 'Remove CCs',
- 'space': 'Shift to Space'
- });
-
- var proj_tokenizer = build_tokenizer(config.sources.project);
- var owner_tokenizer = build_tokenizer(config.sources.owner);
- var cc_tokenizer = build_tokenizer(config.sources.cc);
- var space_tokenizer = build_tokenizer(config.sources.spaces);
-
- var priority_select = JX.Prefab.renderSelect(config.priorityMap);
- var status_select = JX.Prefab.renderSelect(config.statusMap);
- var comment_input = JX.$N('input', {style: {width: '100%'}});
-
- var cell = JX.$N('td', {className: 'batch-editor-input'});
- var vfunc = null;
-
- function update() {
- switch (action_select.value) {
- case 'add_project':
- case 'remove_project':
- JX.DOM.setContent(cell, proj_tokenizer.template);
- vfunc = function() {
- return JX.keys(proj_tokenizer.object.getTokens());
- };
- break;
- case 'add_ccs':
- case 'remove_ccs':
- JX.DOM.setContent(cell, cc_tokenizer.template);
- vfunc = function() {
- return JX.keys(cc_tokenizer.object.getTokens());
- };
- break;
- case 'assign':
- JX.DOM.setContent(cell, owner_tokenizer.template);
- vfunc = function() {
- return JX.keys(owner_tokenizer.object.getTokens());
- };
- break;
- case 'space':
- JX.DOM.setContent(cell, space_tokenizer.template);
- vfunc = function() {
- return JX.keys(space_tokenizer.object.getTokens());
- };
- break;
- case 'add_comment':
- JX.DOM.setContent(cell, comment_input);
- vfunc = function() {
- return comment_input.value;
- };
- break;
- case 'priority':
- JX.DOM.setContent(cell, priority_select);
- vfunc = function() { return priority_select.value; };
- break;
- case 'status':
- JX.DOM.setContent(cell, status_select);
- vfunc = function() { return status_select.value; };
- break;
- }
- }
-
- JX.DOM.listen(action_select, 'change', null, update);
- update();
-
- return {
- nodes : [JX.$N('td', {}, action_select), cell],
- dataCallback : function() {
- return {
- action: action_select.value,
- value: vfunc()
- };
- }
- };
- }
-
- function onaddaction(e) {
- e.kill();
- addRow({});
- }
-
- function addRow(info) {
- var data = renderRow(info);
- var row = manager.addRow(data.nodes);
- var id = manager.getRowID(row);
-
- action_rows[id] = data.dataCallback;
- }
-
- function onsubmit() {
- var input = JX.$(config.input);
-
- var actions = [];
- for (var k in action_rows) {
- actions.push(action_rows[k]());
- }
-
- input.value = JX.JSON.stringify(actions);
- }
-
- addRow({});
-
- JX.DOM.listen(
- root,
- 'click',
- 'add-action',
- onaddaction);
-
- JX.DOM.listen(
- root,
- 'submit',
- null,
- onsubmit);
-
- manager.listen(
- 'row-removed',
- function(row_id) {
- delete action_rows[row_id];
- });
-
- function build_tokenizer(tconfig) {
- var built = JX.Prefab.newTokenizerFromTemplate(
- config.tokenizerTemplate,
- JX.copy({}, tconfig));
- built.tokenizer.start();
-
- return {
- object: built.tokenizer,
- template: built.node
- };
- }
-
-});
diff --git a/webroot/rsrc/js/core/behavior-bulk-editor.js b/webroot/rsrc/js/core/behavior-bulk-editor.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/core/behavior-bulk-editor.js
@@ -0,0 +1,113 @@
+/**
+ * @provides javelin-behavior-bulk-editor
+ * @requires javelin-behavior
+ * javelin-dom
+ * javelin-util
+ * phabricator-prefab
+ * multirow-row-manager
+ * javelin-json
+ * phuix-form-control-view
+ */
+
+JX.behavior('bulk-editor', function(config) {
+
+ var root = JX.$(config.rootNodeID);
+ var editor_table = JX.DOM.find(root, 'table', 'bulk-actions');
+
+ var manager = new JX.MultirowRowManager(editor_table);
+ var action_rows = [];
+
+ var option_map = {};
+ var option_order = [];
+ var spec_map = {};
+
+ for (var ii = 0; ii < config.edits.length; ii++) {
+ var edit = config.edits[ii];
+
+ option_map[edit.xaction] = edit.label;
+ option_order.push(edit.xaction);
+
+ spec_map[edit.xaction] = edit;
+ }
+
+ function renderRow() {
+ var action_select = JX.Prefab.renderSelect(
+ option_map,
+ null,
+ null,
+ option_order);
+
+ var cell = JX.$N('td', {className: 'bulk-edit-input'});
+ var vfunc = null;
+
+ function update() {
+ var spec = spec_map[action_select.value];
+ var control = spec.control;
+
+ var phuix = new JX.PHUIXFormControl()
+ .setControl(control.type, control.spec);
+
+ JX.DOM.setContent(cell, phuix.getRawInputNode());
+
+ vfunc = JX.bind(phuix, phuix.getValue);
+ }
+
+ JX.DOM.listen(action_select, 'change', null, update);
+ update();
+
+ return {
+ nodes : [JX.$N('td', {}, action_select), cell],
+ dataCallback : function() {
+ return {
+ type: action_select.value,
+ value: vfunc()
+ };
+ }
+ };
+ }
+
+ function onaddaction(e) {
+ e.kill();
+ addRow({});
+ }
+
+ function addRow(info) {
+ var data = renderRow(info);
+ var row = manager.addRow(data.nodes);
+ var id = manager.getRowID(row);
+
+ action_rows[id] = data.dataCallback;
+ }
+
+ function onsubmit() {
+ var input = JX.$(config.inputNodeID);
+
+ var actions = [];
+ for (var k in action_rows) {
+ actions.push(action_rows[k]());
+ }
+
+ input.value = JX.JSON.stringify(actions);
+ }
+
+ addRow({});
+
+ JX.DOM.listen(
+ root,
+ 'click',
+ 'add-action',
+ onaddaction);
+
+ JX.DOM.listen(
+ root,
+ 'submit',
+ null,
+ onsubmit);
+
+ manager.listen(
+ 'row-removed',
+ function(row_id) {
+ delete action_rows[row_id];
+ });
+
+});
diff --git a/webroot/rsrc/js/phuix/PHUIXFormControl.js b/webroot/rsrc/js/phuix/PHUIXFormControl.js
--- a/webroot/rsrc/js/phuix/PHUIXFormControl.js
+++ b/webroot/rsrc/js/phuix/PHUIXFormControl.js
@@ -14,6 +14,7 @@
_className: null,
_valueSetCallback: null,
_valueGetCallback: null,
+ _rawInputNode: null,
setLabel: function(label) {
JX.DOM.setContent(this._getLabelNode(), label);
@@ -53,6 +54,9 @@
case 'checkboxes':
input = this._newCheckboxes(spec);
break;
+ case 'text':
+ input = this._newText(spec);
+ break;
default:
// TODO: Default or better error?
JX.$E('Bad Input Type');
@@ -62,6 +66,7 @@
JX.DOM.setContent(node, input.node);
this._valueGetCallback = input.get;
this._valueSetCallback = input.set;
+ this._rawInputNode = input.node;
return this;
},
@@ -75,6 +80,10 @@
return this._valueGetCallback();
},
+ getRawInputNode: function() {
+ return this._rawInputNode;
+ },
+
getNode: function() {
if (!this._node) {
@@ -281,6 +290,10 @@
},
_newPoints: function(spec) {
+ return this._newText();
+ },
+
+ _newText: function(spec) {
var attrs = {
type: 'text',
value: spec.value
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Oct 5, 4:09 AM (20 h, 5 m)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/2a/qf/ztfm2dpcaiuuz552
Default Alt Text
D18863.diff (32 KB)
Attached To
Mode
D18863: Define bulk edits in terms of EditEngine, not hard-coded ad-hoc definitions
Attached
Detach File
Event Timeline
Log In to Comment