Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15281201
D16164.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
5 KB
Referenced Files
None
Subscribers
None
D16164.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
@@ -11,7 +11,7 @@
'core.pkg.js' => 'f2139810',
'darkconsole.pkg.js' => 'e7393ebb',
'differential.pkg.css' => 'b3eea3f5',
- 'differential.pkg.js' => '4b7d8f19',
+ 'differential.pkg.js' => '01a010d6',
'diffusion.pkg.css' => '91c5d3a6',
'diffusion.pkg.js' => '3a9a8bfa',
'maniphest.pkg.css' => '4845691a',
@@ -495,7 +495,7 @@
'rsrc/js/core/behavior-lightbox-attachments.js' => 'f8ba29d7',
'rsrc/js/core/behavior-line-linker.js' => '1499a8cb',
'rsrc/js/core/behavior-more.js' => 'a80d0378',
- 'rsrc/js/core/behavior-object-selector.js' => '49b73b36',
+ 'rsrc/js/core/behavior-object-selector.js' => '9030ebef',
'rsrc/js/core/behavior-oncopy.js' => '2926fff2',
'rsrc/js/core/behavior-phabricator-nav.js' => '56a1ca03',
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '116cf19b',
@@ -658,7 +658,7 @@
'javelin-behavior-phabricator-line-linker' => '1499a8cb',
'javelin-behavior-phabricator-nav' => '56a1ca03',
'javelin-behavior-phabricator-notification-example' => '8ce821c5',
- 'javelin-behavior-phabricator-object-selector' => '49b73b36',
+ 'javelin-behavior-phabricator-object-selector' => '9030ebef',
'javelin-behavior-phabricator-oncopy' => '2926fff2',
'javelin-behavior-phabricator-remarkup-assist' => '116cf19b',
'javelin-behavior-phabricator-reveal-content' => '60821bc7',
@@ -1214,12 +1214,6 @@
'javelin-uri',
'phabricator-notification',
),
- '49b73b36' => array(
- 'javelin-behavior',
- 'javelin-dom',
- 'javelin-request',
- 'javelin-util',
- ),
'4b700e9e' => array(
'javelin-behavior',
'javelin-dom',
@@ -1608,6 +1602,12 @@
'javelin-dom',
'javelin-request',
),
+ '9030ebef' => array(
+ 'javelin-behavior',
+ 'javelin-dom',
+ 'javelin-request',
+ 'javelin-util',
+ ),
'9196fb06' => array(
'javelin-install',
'javelin-dom',
diff --git a/src/applications/search/controller/PhabricatorSearchRelationshipController.php b/src/applications/search/controller/PhabricatorSearchRelationshipController.php
--- a/src/applications/search/controller/PhabricatorSearchRelationshipController.php
+++ b/src/applications/search/controller/PhabricatorSearchRelationshipController.php
@@ -44,18 +44,20 @@
$src_handle = $handles[$src_phid];
$done_uri = $src_handle->getURI();
+ $initial_phids = $dst_phids;
if ($request->isFormPost()) {
$phids = explode(';', $request->getStr('phids'));
$phids = array_filter($phids);
$phids = array_values($phids);
- // TODO: Embed these in the form instead, to gracefully resolve
- // concurrent edits like we do for subscribers and projects.
- $old_phids = $dst_phids;
+ $initial_phids = $request->getStrList('initialPHIDs');
- $add_phids = $phids;
- $rem_phids = array_diff($old_phids, $add_phids);
+ // Apply the changes as adds and removes relative to the original state
+ // of the object when the dialog was rendered so that two users adding
+ // relationships at the same time don't race and overwrite one another.
+ $add_phids = array_diff($phids, $initial_phids);
+ $rem_phids = array_diff($initial_phids, $phids);
if ($add_phids) {
$dst_objects = id(new PhabricatorObjectQuery())
@@ -149,6 +151,7 @@
return id(new PhabricatorObjectSelectorDialog())
->setUser($viewer)
+ ->setInitialPHIDs($initial_phids)
->setHandles($handles)
->setFilters($filters)
->setSelectedFilter('created')
diff --git a/src/view/control/PhabricatorObjectSelectorDialog.php b/src/view/control/PhabricatorObjectSelectorDialog.php
--- a/src/view/control/PhabricatorObjectSelectorDialog.php
+++ b/src/view/control/PhabricatorObjectSelectorDialog.php
@@ -10,6 +10,7 @@
private $searchURI;
private $selectedFilter;
private $excluded;
+ private $initialPHIDs;
private $title;
private $header;
@@ -77,6 +78,15 @@
return $this;
}
+ public function setInitialPHIDs(array $initial_phids) {
+ $this->initialPHIDs = $initial_phids;
+ return $this;
+ }
+
+ public function getInitialPHIDs() {
+ return $this->initialPHIDs;
+ }
+
public function buildDialog() {
$user = $this->user;
@@ -171,8 +181,14 @@
$view = new PhabricatorHandleObjectSelectorDataView($handle);
$handle_views[$phid] = $view->renderData();
}
+
$dialog->addHiddenInput('phids', implode(';', array_keys($this->handles)));
+ $initial_phids = $this->getInitialPHIDs();
+ if ($initial_phids) {
+ $initial_phids = implode(', ', $initial_phids);
+ $dialog->addHiddenInput('initialPHIDs', $initial_phids);
+ }
Javelin::initBehavior(
'phabricator-object-selector',
diff --git a/webroot/rsrc/js/core/behavior-object-selector.js b/webroot/rsrc/js/core/behavior-object-selector.js
--- a/webroot/rsrc/js/core/behavior-object-selector.js
+++ b/webroot/rsrc/js/core/behavior-object-selector.js
@@ -18,10 +18,21 @@
var query_timer = null;
var query_delay = 50;
- var phid_input = JX.DOM.find(
+ // TODO: This is fairly grotesque, but the dialog has two different forms
+ // inside it and there's no way to sigil the inputs in the "real" form right
+ // now. Clean this up when the dialog as a whole gets cleaned up.
+
+ var inputs = JX.DOM.scry(
JX.$(config.form),
'input',
'aphront-dialog-application-input');
+ var phid_input;
+ for (var ii = 0; ii < inputs.length; ii++) {
+ if (inputs[ii].name == 'phids') {
+ phid_input = inputs[ii];
+ break;
+ }
+ }
var last_value = JX.$(config.query).value;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Mar 4, 4:19 PM (18 h, 52 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7222148
Default Alt Text
D16164.diff (5 KB)
Attached To
Mode
D16164: Resolve relationship edit conflicts more naturally
Attached
Detach File
Event Timeline
Log In to Comment