mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 16:52:41 +01:00
Allow "Custom" policies to be selected in the policy control
Summary: Ref T603. When a user selects "Custom", we pop open the rules dialog and let them create a new rule or edit the existing rule. Test Plan: Set some objects to have custom policies. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T603 Differential Revision: https://secure.phabricator.com/D7300
This commit is contained in:
parent
3a4c08d7f1
commit
76dfeb95ba
5 changed files with 135 additions and 15 deletions
|
@ -2295,7 +2295,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-behavior-policy-control' =>
|
||||
array(
|
||||
'uri' => '/res/f43ba427/rsrc/js/application/policy/behavior-policy-control.js',
|
||||
'uri' => '/res/ce9f54c8/rsrc/js/application/policy/behavior-policy-control.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -2304,6 +2304,7 @@ celerity_register_resource_map(array(
|
|||
2 => 'javelin-util',
|
||||
3 => 'phabricator-dropdown-menu',
|
||||
4 => 'phabricator-menu-item',
|
||||
5 => 'javelin-workflow',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/policy/behavior-policy-control.js',
|
||||
),
|
||||
|
|
|
@ -47,9 +47,17 @@ final class PhabricatorApplicationEditController
|
|||
}
|
||||
|
||||
if (empty($policies[$new])) {
|
||||
// Can't set the policy to something invalid.
|
||||
// Not a standard policy, check for a custom policy.
|
||||
$policy = id(new PhabricatorPolicyQuery())
|
||||
->setViewer($user)
|
||||
->withPHIDs(array($new))
|
||||
->executeOne();
|
||||
if (!$policy) {
|
||||
// Not a custom policy either. Can't set the policy to something
|
||||
// invalid, so skip this.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($new == PhabricatorPolicies::POLICY_PUBLIC) {
|
||||
$capobj = PhabricatorPolicyCapability::getCapabilityByKey(
|
||||
|
|
|
@ -10,7 +10,7 @@ final class PhabricatorPolicyRuleProjects
|
|||
}
|
||||
|
||||
public function willApplyRules(PhabricatorUser $viewer, array $values) {
|
||||
$values = array_unique(array_filter($values));
|
||||
$values = array_unique(array_filter(array_mergev($values)));
|
||||
if (!$values) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,48 @@ final class AphrontFormPolicyControl extends AphrontFormControl {
|
|||
'icon' => $policy->getIcon(),
|
||||
);
|
||||
}
|
||||
|
||||
// If we were passed several custom policy options, throw away the ones
|
||||
// which aren't the value for this capability. For example, an object might
|
||||
// have a custom view pollicy and a custom edit policy. When we render
|
||||
// the selector for "Can View", we don't want to show the "Can Edit"
|
||||
// custom policy -- if we did, the menu would look like this:
|
||||
//
|
||||
// Custom
|
||||
// Custom Policy
|
||||
// Custom Policy
|
||||
//
|
||||
// ...where one is the "view" custom policy, and one is the "edit" custom
|
||||
// policy.
|
||||
|
||||
$type_custom = PhabricatorPolicyType::TYPE_CUSTOM;
|
||||
if (!empty($options[$type_custom])) {
|
||||
$options[$type_custom] = array_select_keys(
|
||||
$options[$type_custom],
|
||||
array($this->getValue()));
|
||||
}
|
||||
|
||||
// If there aren't any custom policies, add a placeholder policy so we
|
||||
// render a menu item. This allows the user to switch to a custom policy.
|
||||
|
||||
if (empty($options[$type_custom])) {
|
||||
$placeholder = new PhabricatorPolicy();
|
||||
$placeholder->setName(pht('Custom Policy...'));
|
||||
$options[$type_custom][$this->getCustomPolicyPlaceholder()] = array(
|
||||
'name' => $placeholder->getName(),
|
||||
'full' => $placeholder->getName(),
|
||||
'icon' => $placeholder->getIcon(),
|
||||
);
|
||||
}
|
||||
|
||||
$options = array_select_keys(
|
||||
$options,
|
||||
array(
|
||||
PhabricatorPolicyType::TYPE_GLOBAL,
|
||||
PhabricatorPolicyType::TYPE_CUSTOM,
|
||||
PhabricatorPolicyType::TYPE_PROJECT,
|
||||
));
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
|
@ -121,6 +163,7 @@ final class AphrontFormPolicyControl extends AphrontFormControl {
|
|||
'icons' => $icons,
|
||||
'labels' => $labels,
|
||||
'value' => $this->getValue(),
|
||||
'customPlaceholder' => $this->getCustomPolicyPlaceholder(),
|
||||
));
|
||||
|
||||
$selected = $flat_options[$this->getValue()];
|
||||
|
@ -165,5 +208,8 @@ final class AphrontFormPolicyControl extends AphrontFormControl {
|
|||
));
|
||||
}
|
||||
|
||||
private function getCustomPolicyPlaceholder() {
|
||||
return 'custom:placeholder';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* javelin-util
|
||||
* phabricator-dropdown-menu
|
||||
* phabricator-menu-item
|
||||
* javelin-workflow
|
||||
* @javelin
|
||||
*/
|
||||
JX.behavior('policy-control', function(config) {
|
||||
|
@ -23,25 +24,37 @@ JX.behavior('policy-control', function(config) {
|
|||
for (var ii = 0; ii < config.groups.length; ii++) {
|
||||
var group = config.groups[ii];
|
||||
|
||||
var header = new JX.PhabricatorMenuItem(config.labels[group]);
|
||||
var header = new JX.PhabricatorMenuItem(config.labels[group], JX.bag);
|
||||
header.setDisabled(true);
|
||||
menu.addItem(header);
|
||||
|
||||
for (var jj = 0; jj < config.order[group].length; jj++) {
|
||||
var phid = config.order[group][jj];
|
||||
var option = config.options[phid];
|
||||
|
||||
var render = [JX.$H(config.icons[option.icon]), option.name];
|
||||
var onselect;
|
||||
if (group == 'custom') {
|
||||
onselect = JX.bind(null, function(phid) {
|
||||
var uri = get_custom_uri(phid);
|
||||
|
||||
new JX.Workflow(uri)
|
||||
.setHandler(function(response) {
|
||||
if (!response.phid) {
|
||||
return;
|
||||
}
|
||||
|
||||
replace_policy(phid, response.phid, response.info);
|
||||
select_policy(response.phid);
|
||||
})
|
||||
.start();
|
||||
|
||||
}, phid);
|
||||
} else {
|
||||
onselect = JX.bind(null, select_policy, phid);
|
||||
}
|
||||
|
||||
var item = new JX.PhabricatorMenuItem(
|
||||
render,
|
||||
JX.bind(null, function(phid, render) {
|
||||
JX.DOM.setContent(
|
||||
JX.DOM.find(control, 'span', 'policy-label'),
|
||||
render);
|
||||
input.value = phid;
|
||||
value = phid;
|
||||
}, phid, render));
|
||||
render_option(phid, true),
|
||||
onselect);
|
||||
|
||||
if (phid == value) {
|
||||
item.setSelected(true);
|
||||
|
@ -53,4 +66,56 @@ JX.behavior('policy-control', function(config) {
|
|||
|
||||
});
|
||||
|
||||
|
||||
var select_policy = function(phid) {
|
||||
JX.DOM.setContent(
|
||||
JX.DOM.find(control, 'span', 'policy-label'),
|
||||
render_option(phid));
|
||||
|
||||
input.value = phid;
|
||||
value = phid;
|
||||
};
|
||||
|
||||
|
||||
var render_option = function(phid, with_title) {
|
||||
var option = config.options[phid];
|
||||
|
||||
var name = option.name;
|
||||
if (with_title && (option.full != option.name)) {
|
||||
name = JX.$N('span', {title: option.full}, name);
|
||||
}
|
||||
|
||||
return [JX.$H(config.icons[option.icon]), name];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the workflow URI to create or edit a policy with a given PHID.
|
||||
*/
|
||||
var get_custom_uri = function(phid) {
|
||||
var uri = '/policy/edit/';
|
||||
if (phid != config.customPlaceholder) {
|
||||
uri += phid + '/';
|
||||
}
|
||||
return uri;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Replace an existing policy option with a new one. Used to swap out custom
|
||||
* policies after the user edits them.
|
||||
*/
|
||||
var replace_policy = function(old_phid, new_phid, info) {
|
||||
config.options[new_phid] = info;
|
||||
for (var k in config.order) {
|
||||
for (var ii = 0; ii < config.order[k].length; ii++) {
|
||||
if (config.order[k][ii] == old_phid) {
|
||||
config.order[k][ii] = new_phid;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue