1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 23:02:42 +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:
epriestley 2013-10-14 16:59:16 -07:00
parent 3a4c08d7f1
commit 76dfeb95ba
5 changed files with 135 additions and 15 deletions

View file

@ -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',
),

View file

@ -47,8 +47,16 @@ final class PhabricatorApplicationEditController
}
if (empty($policies[$new])) {
// Can't set the policy to something invalid.
continue;
// 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) {

View file

@ -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;
}

View file

@ -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';
}
}

View file

@ -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;
}
}
}
};
});