mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-18 12:52:42 +01:00
Add CustomField support to Owners
Summary: Fixes T9351. This is straightforward since this application is now relatively modern and doesn't have any bizarre craziness. Test Plan: {F787981} {F787982} Reviewers: chad Reviewed By: chad Maniphest Tasks: T9351 Differential Revision: https://secure.phabricator.com/D14093
This commit is contained in:
parent
093a625698
commit
f8080ce931
12 changed files with 233 additions and 40 deletions
25
resources/sql/autopatches/20150910.owners.custom.1.sql
Normal file
25
resources/sql/autopatches/20150910.owners.custom.1.sql
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
CREATE TABLE {$NAMESPACE}_owners.owners_customfieldstorage (
|
||||||
|
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
objectPHID VARBINARY(64) NOT NULL,
|
||||||
|
fieldIndex BINARY(12) NOT NULL,
|
||||||
|
fieldValue LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
|
||||||
|
UNIQUE KEY (objectPHID, fieldIndex)
|
||||||
|
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
||||||
|
|
||||||
|
CREATE TABLE {$NAMESPACE}_owners.owners_customfieldstringindex (
|
||||||
|
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
objectPHID VARBINARY(64) NOT NULL,
|
||||||
|
indexKey BINARY(12) NOT NULL,
|
||||||
|
indexValue LONGTEXT NOT NULL COLLATE {$COLLATE_SORT},
|
||||||
|
KEY `key_join` (objectPHID, indexKey, indexValue(64)),
|
||||||
|
KEY `key_find` (indexKey, indexValue(64))
|
||||||
|
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
||||||
|
|
||||||
|
CREATE TABLE {$NAMESPACE}_owners.owners_customfieldnumericindex (
|
||||||
|
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
objectPHID VARBINARY(64) NOT NULL,
|
||||||
|
indexKey BINARY(12) NOT NULL,
|
||||||
|
indexValue BIGINT NOT NULL,
|
||||||
|
KEY `key_join` (objectPHID, indexKey, indexValue),
|
||||||
|
KEY `key_find` (indexKey, indexValue)
|
||||||
|
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
|
@ -2437,7 +2437,12 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorOwnerPathQuery' => 'applications/owners/query/PhabricatorOwnerPathQuery.php',
|
'PhabricatorOwnerPathQuery' => 'applications/owners/query/PhabricatorOwnerPathQuery.php',
|
||||||
'PhabricatorOwnersApplication' => 'applications/owners/application/PhabricatorOwnersApplication.php',
|
'PhabricatorOwnersApplication' => 'applications/owners/application/PhabricatorOwnersApplication.php',
|
||||||
'PhabricatorOwnersConfigOptions' => 'applications/owners/config/PhabricatorOwnersConfigOptions.php',
|
'PhabricatorOwnersConfigOptions' => 'applications/owners/config/PhabricatorOwnersConfigOptions.php',
|
||||||
|
'PhabricatorOwnersConfiguredCustomField' => 'applications/owners/customfield/PhabricatorOwnersConfiguredCustomField.php',
|
||||||
'PhabricatorOwnersController' => 'applications/owners/controller/PhabricatorOwnersController.php',
|
'PhabricatorOwnersController' => 'applications/owners/controller/PhabricatorOwnersController.php',
|
||||||
|
'PhabricatorOwnersCustomField' => 'applications/owners/customfield/PhabricatorOwnersCustomField.php',
|
||||||
|
'PhabricatorOwnersCustomFieldNumericIndex' => 'applications/owners/storage/PhabricatorOwnersCustomFieldNumericIndex.php',
|
||||||
|
'PhabricatorOwnersCustomFieldStorage' => 'applications/owners/storage/PhabricatorOwnersCustomFieldStorage.php',
|
||||||
|
'PhabricatorOwnersCustomFieldStringIndex' => 'applications/owners/storage/PhabricatorOwnersCustomFieldStringIndex.php',
|
||||||
'PhabricatorOwnersDAO' => 'applications/owners/storage/PhabricatorOwnersDAO.php',
|
'PhabricatorOwnersDAO' => 'applications/owners/storage/PhabricatorOwnersDAO.php',
|
||||||
'PhabricatorOwnersDetailController' => 'applications/owners/controller/PhabricatorOwnersDetailController.php',
|
'PhabricatorOwnersDetailController' => 'applications/owners/controller/PhabricatorOwnersDetailController.php',
|
||||||
'PhabricatorOwnersEditController' => 'applications/owners/controller/PhabricatorOwnersEditController.php',
|
'PhabricatorOwnersEditController' => 'applications/owners/controller/PhabricatorOwnersEditController.php',
|
||||||
|
@ -6425,7 +6430,15 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorOwnerPathQuery' => 'Phobject',
|
'PhabricatorOwnerPathQuery' => 'Phobject',
|
||||||
'PhabricatorOwnersApplication' => 'PhabricatorApplication',
|
'PhabricatorOwnersApplication' => 'PhabricatorApplication',
|
||||||
'PhabricatorOwnersConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
'PhabricatorOwnersConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||||
|
'PhabricatorOwnersConfiguredCustomField' => array(
|
||||||
|
'PhabricatorOwnersCustomField',
|
||||||
|
'PhabricatorStandardCustomFieldInterface',
|
||||||
|
),
|
||||||
'PhabricatorOwnersController' => 'PhabricatorController',
|
'PhabricatorOwnersController' => 'PhabricatorController',
|
||||||
|
'PhabricatorOwnersCustomField' => 'PhabricatorCustomField',
|
||||||
|
'PhabricatorOwnersCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage',
|
||||||
|
'PhabricatorOwnersCustomFieldStorage' => 'PhabricatorCustomFieldStorage',
|
||||||
|
'PhabricatorOwnersCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage',
|
||||||
'PhabricatorOwnersDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorOwnersDAO' => 'PhabricatorLiskDAO',
|
||||||
'PhabricatorOwnersDetailController' => 'PhabricatorOwnersController',
|
'PhabricatorOwnersDetailController' => 'PhabricatorOwnersController',
|
||||||
'PhabricatorOwnersEditController' => 'PhabricatorOwnersController',
|
'PhabricatorOwnersEditController' => 'PhabricatorOwnersController',
|
||||||
|
@ -6435,6 +6448,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorOwnersDAO',
|
'PhabricatorOwnersDAO',
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
'PhabricatorApplicationTransactionInterface',
|
'PhabricatorApplicationTransactionInterface',
|
||||||
|
'PhabricatorCustomFieldInterface',
|
||||||
),
|
),
|
||||||
'PhabricatorOwnersPackageDatasource' => 'PhabricatorTypeaheadDatasource',
|
'PhabricatorOwnersPackageDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||||
'PhabricatorOwnersPackageFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
'PhabricatorOwnersPackageFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||||
|
|
|
@ -20,9 +20,35 @@ final class PhabricatorOwnersConfigOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOptions() {
|
public function getOptions() {
|
||||||
|
$custom_field_type = 'custom:PhabricatorCustomFieldConfigOptionType';
|
||||||
|
$default_fields = array();
|
||||||
|
|
||||||
|
$field_base_class = id(new PhabricatorOwnersPackage())
|
||||||
|
->getCustomFieldBaseClass();
|
||||||
|
|
||||||
|
$fields_example = array(
|
||||||
|
'mycompany:lore' => array(
|
||||||
|
'name' => pht('Package Lore'),
|
||||||
|
'type' => 'remarkup',
|
||||||
|
'caption' => pht('Tales of adventure for this package.'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$fields_example = id(new PhutilJSON())->encodeFormatted($fields_example);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
$this->newOption('metamta.package.subject-prefix', 'string', '[Package]')
|
$this->newOption('metamta.package.subject-prefix', 'string', '[Package]')
|
||||||
->setDescription(pht('Subject prefix for Owners email.')),
|
->setDescription(pht('Subject prefix for Owners email.')),
|
||||||
|
$this->newOption('owners.fields', $custom_field_type, $default_fields)
|
||||||
|
->setCustomData($field_base_class)
|
||||||
|
->setDescription(pht('Select and reorder package fields.')),
|
||||||
|
$this->newOption('owners.custom-field-definitions', 'wild', array())
|
||||||
|
->setSummary(pht('Custom Owners fields.'))
|
||||||
|
->setDescription(
|
||||||
|
pht(
|
||||||
|
'Map of custom fields for Owners packages. For details on '.
|
||||||
|
'adding custom fields to Owners, see "Configuring Custom '.
|
||||||
|
'Fields" in the documentation.'))
|
||||||
|
->addExample($fields_example, pht('Valid Setting')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,15 @@ final class PhabricatorOwnersDetailController
|
||||||
$repositories = array();
|
$repositories = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$field_list = PhabricatorCustomField::getObjectFields(
|
||||||
|
$package,
|
||||||
|
PhabricatorCustomField::ROLE_VIEW);
|
||||||
|
$field_list
|
||||||
|
->setViewer($viewer)
|
||||||
|
->readFieldsFromStorage($package);
|
||||||
|
|
||||||
$actions = $this->buildPackageActionView($package);
|
$actions = $this->buildPackageActionView($package);
|
||||||
$properties = $this->buildPackagePropertyView($package);
|
$properties = $this->buildPackagePropertyView($package, $field_list);
|
||||||
$properties->setActionList($actions);
|
$properties->setActionList($actions);
|
||||||
|
|
||||||
if ($package->isArchived()) {
|
if ($package->isArchived()) {
|
||||||
|
@ -156,7 +163,10 @@ final class PhabricatorOwnersDetailController
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function buildPackagePropertyView(PhabricatorOwnersPackage $package) {
|
private function buildPackagePropertyView(
|
||||||
|
PhabricatorOwnersPackage $package,
|
||||||
|
PhabricatorCustomFieldList $field_list) {
|
||||||
|
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
$view = id(new PHUIPropertyListView())
|
$view = id(new PHUIPropertyListView())
|
||||||
|
@ -187,6 +197,13 @@ final class PhabricatorOwnersDetailController
|
||||||
$viewer));
|
$viewer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$view->invokeWillRenderEvent();
|
||||||
|
|
||||||
|
$field_list->appendFieldsToPropertyList(
|
||||||
|
$package,
|
||||||
|
$viewer,
|
||||||
|
$view);
|
||||||
|
|
||||||
return $view;
|
return $view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,11 @@ final class PhabricatorOwnersEditController
|
||||||
$v_description = $package->getDescription();
|
$v_description = $package->getDescription();
|
||||||
$v_status = $package->getStatus();
|
$v_status = $package->getStatus();
|
||||||
|
|
||||||
|
$field_list = PhabricatorCustomField::getObjectFields(
|
||||||
|
$package,
|
||||||
|
PhabricatorCustomField::ROLE_EDIT);
|
||||||
|
$field_list->setViewer($viewer);
|
||||||
|
$field_list->readFieldsFromStorage($package);
|
||||||
|
|
||||||
$errors = array();
|
$errors = array();
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
|
@ -75,6 +80,12 @@ final class PhabricatorOwnersEditController
|
||||||
->setNewValue($v_status);
|
->setNewValue($v_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$field_xactions = $field_list->buildFieldTransactionsFromRequest(
|
||||||
|
new PhabricatorOwnersPackageTransaction(),
|
||||||
|
$request);
|
||||||
|
|
||||||
|
$xactions = array_merge($xactions, $field_xactions);
|
||||||
|
|
||||||
$editor = id(new PhabricatorOwnersPackageTransactionEditor())
|
$editor = id(new PhabricatorOwnersPackageTransactionEditor())
|
||||||
->setActor($viewer)
|
->setActor($viewer)
|
||||||
->setContentSourceFromRequest($request)
|
->setContentSourceFromRequest($request)
|
||||||
|
@ -126,41 +137,44 @@ final class PhabricatorOwnersEditController
|
||||||
->setName('owners')
|
->setName('owners')
|
||||||
->setValue($v_owners));
|
->setValue($v_owners));
|
||||||
|
|
||||||
if (!$is_new) {
|
if (!$is_new) {
|
||||||
$form->appendChild(
|
|
||||||
id(new AphrontFormSelectControl())
|
|
||||||
->setLabel(pht('Status'))
|
|
||||||
->setName('status')
|
|
||||||
->setValue($v_status)
|
|
||||||
->setOptions($package->getStatusNameMap()));
|
|
||||||
}
|
|
||||||
|
|
||||||
$form->appendChild(
|
$form->appendChild(
|
||||||
id(new AphrontFormSelectControl())
|
id(new AphrontFormSelectControl())
|
||||||
->setName('auditing')
|
->setLabel(pht('Status'))
|
||||||
->setLabel(pht('Auditing'))
|
->setName('status')
|
||||||
->setCaption(
|
->setValue($v_status)
|
||||||
pht(
|
->setOptions($package->getStatusNameMap()));
|
||||||
'With auditing enabled, all future commits that touch '.
|
}
|
||||||
'this package will be reviewed to make sure an owner '.
|
|
||||||
'of the package is involved and the commit message has '.
|
$form->appendChild(
|
||||||
'a valid revision, reviewed by, and author.'))
|
id(new AphrontFormSelectControl())
|
||||||
->setOptions(
|
->setName('auditing')
|
||||||
array(
|
->setLabel(pht('Auditing'))
|
||||||
'disabled' => pht('Disabled'),
|
->setCaption(
|
||||||
'enabled' => pht('Enabled'),
|
pht(
|
||||||
))
|
'With auditing enabled, all future commits that touch '.
|
||||||
->setValue(($v_auditing ? 'enabled' : 'disabled')))
|
'this package will be reviewed to make sure an owner '.
|
||||||
|
'of the package is involved and the commit message has '.
|
||||||
|
'a valid revision, reviewed by, and author.'))
|
||||||
|
->setOptions(
|
||||||
|
array(
|
||||||
|
'disabled' => pht('Disabled'),
|
||||||
|
'enabled' => pht('Enabled'),
|
||||||
|
))
|
||||||
|
->setValue(($v_auditing ? 'enabled' : 'disabled')))
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new PhabricatorRemarkupControl())
|
id(new PhabricatorRemarkupControl())
|
||||||
->setUser($viewer)
|
->setUser($viewer)
|
||||||
->setLabel(pht('Description'))
|
->setLabel(pht('Description'))
|
||||||
->setName('description')
|
->setName('description')
|
||||||
->setValue($v_description))
|
->setValue($v_description));
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormSubmitControl())
|
$field_list->appendFieldsToForm($form);
|
||||||
->addCancelButton($cancel_uri)
|
|
||||||
->setValue($button_text));
|
$form->appendChild(
|
||||||
|
id(new AphrontFormSubmitControl())
|
||||||
|
->addCancelButton($cancel_uri)
|
||||||
|
->setValue($button_text));
|
||||||
|
|
||||||
$form_box = id(new PHUIObjectBoxView())
|
$form_box = id(new PHUIObjectBoxView())
|
||||||
->setHeaderText($title)
|
->setHeaderText($title)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorOwnersConfiguredCustomField
|
||||||
|
extends PhabricatorOwnersCustomField
|
||||||
|
implements PhabricatorStandardCustomFieldInterface {
|
||||||
|
|
||||||
|
public function getStandardCustomFieldNamespace() {
|
||||||
|
return 'owners';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createFields($object) {
|
||||||
|
$config = PhabricatorEnv::getEnvConfig(
|
||||||
|
'owners.custom-field-definitions',
|
||||||
|
array());
|
||||||
|
|
||||||
|
$fields = PhabricatorStandardCustomField::buildStandardFields(
|
||||||
|
$this,
|
||||||
|
$config);
|
||||||
|
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhabricatorOwnersCustomField
|
||||||
|
extends PhabricatorCustomField {
|
||||||
|
|
||||||
|
public function newStorageObject() {
|
||||||
|
return new PhabricatorOwnersCustomFieldStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newStringIndexStorage() {
|
||||||
|
return new PhabricatorOwnersCustomFieldStringIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newNumericIndexStorage() {
|
||||||
|
return new PhabricatorOwnersCustomFieldNumericIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorOwnersCustomFieldNumericIndex
|
||||||
|
extends PhabricatorCustomFieldNumericIndexStorage {
|
||||||
|
|
||||||
|
public function getApplicationName() {
|
||||||
|
return 'owners';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorOwnersCustomFieldStorage
|
||||||
|
extends PhabricatorCustomFieldStorage {
|
||||||
|
|
||||||
|
public function getApplicationName() {
|
||||||
|
return 'owners';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorOwnersCustomFieldStringIndex
|
||||||
|
extends PhabricatorCustomFieldStringIndexStorage {
|
||||||
|
|
||||||
|
public function getApplicationName() {
|
||||||
|
return 'owners';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,7 +4,8 @@ final class PhabricatorOwnersPackage
|
||||||
extends PhabricatorOwnersDAO
|
extends PhabricatorOwnersDAO
|
||||||
implements
|
implements
|
||||||
PhabricatorPolicyInterface,
|
PhabricatorPolicyInterface,
|
||||||
PhabricatorApplicationTransactionInterface {
|
PhabricatorApplicationTransactionInterface,
|
||||||
|
PhabricatorCustomFieldInterface {
|
||||||
|
|
||||||
protected $name;
|
protected $name;
|
||||||
protected $originalName;
|
protected $originalName;
|
||||||
|
@ -16,6 +17,7 @@ final class PhabricatorOwnersPackage
|
||||||
|
|
||||||
private $paths = self::ATTACHABLE;
|
private $paths = self::ATTACHABLE;
|
||||||
private $owners = self::ATTACHABLE;
|
private $owners = self::ATTACHABLE;
|
||||||
|
private $customFields = self::ATTACHABLE;
|
||||||
|
|
||||||
const STATUS_ACTIVE = 'active';
|
const STATUS_ACTIVE = 'active';
|
||||||
const STATUS_ARCHIVED = 'archived';
|
const STATUS_ARCHIVED = 'archived';
|
||||||
|
@ -304,4 +306,25 @@ final class PhabricatorOwnersPackage
|
||||||
return $timeline;
|
return $timeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( PhabricatorCustomFieldInterface )------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
|
public function getCustomFieldSpecificationForRole($role) {
|
||||||
|
return PhabricatorEnv::getEnvConfig('owners.fields');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCustomFieldBaseClass() {
|
||||||
|
return 'PhabricatorOwnersCustomField';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCustomFields() {
|
||||||
|
return $this->assertAttached($this->customFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
|
||||||
|
$this->customFields = $fields;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,12 @@ These applications currently support custom fields:
|
||||||
|
|
||||||
| Application | Support |
|
| Application | Support |
|
||||||
|-------------|---------|
|
|-------------|---------|
|
||||||
| Maniphest | Full Support |
|
|
||||||
| Projects | Full Support |
|
|
||||||
| People | Full Support |
|
|
||||||
| Differential | Partial Support |
|
| Differential | Partial Support |
|
||||||
| Diffusion | Limited Support |
|
| Diffusion | Limited Support |
|
||||||
|
| Maniphest | Full Support |
|
||||||
|
| Owners | Full Support |
|
||||||
|
| People | Full Support |
|
||||||
|
| Projects | Full Support |
|
||||||
|
|
||||||
Custom fields can appear in many interfaces and support search, editing, and
|
Custom fields can appear in many interfaces and support search, editing, and
|
||||||
other features.
|
other features.
|
||||||
|
@ -38,11 +39,12 @@ The relevant configuration settings are:
|
||||||
|
|
||||||
| Application | Add Fields | Select Fields |
|
| Application | Add Fields | Select Fields |
|
||||||
|-------------|------------|---------------|
|
|-------------|------------|---------------|
|
||||||
| Maniphest | `maniphest.custom-field-definitions` | `maniphest.fields` |
|
|
||||||
| Projects | `projects.custom-field-definitions` | `projects.fields` |
|
|
||||||
| People | `user.custom-field-definitions` | `user.fields` |
|
|
||||||
| Differential | Planned | `differential.fields` |
|
| Differential | Planned | `differential.fields` |
|
||||||
| Diffusion | Planned | Planned |
|
| Diffusion | Planned | Planned |
|
||||||
|
| Maniphest | `maniphest.custom-field-definitions` | `maniphest.fields` |
|
||||||
|
| Owners | `owners.custom-field-definitions` | `owners.fields` |
|
||||||
|
| People | `user.custom-field-definitions` | `user.fields` |
|
||||||
|
| Projects | `projects.custom-field-definitions` | `projects.fields` |
|
||||||
|
|
||||||
When adding fields, you'll specify a JSON blob like this (for example, as the
|
When adding fields, you'll specify a JSON blob like this (for example, as the
|
||||||
value of `maniphest.custom-field-definitions`):
|
value of `maniphest.custom-field-definitions`):
|
||||||
|
@ -157,11 +159,12 @@ want to add a field to:
|
||||||
|
|
||||||
| Application | Extend |
|
| Application | Extend |
|
||||||
|-------------|---------|
|
|-------------|---------|
|
||||||
| Maniphest | @{class:ManiphestCustomField} |
|
|
||||||
| Projects | @{class:PhabricatorProjectCustomField} |
|
|
||||||
| People | @{class:PhabricatorUserCustomField} |
|
|
||||||
| Differential | @{class:DifferentialCustomField} |
|
| Differential | @{class:DifferentialCustomField} |
|
||||||
| Diffusion | @{class:PhabricatorCommitCustomField} |
|
| Diffusion | @{class:PhabricatorCommitCustomField} |
|
||||||
|
| Maniphest | @{class:ManiphestCustomField} |
|
||||||
|
| Owners | @{class:PhabricatorOwnersCustomField} |
|
||||||
|
| People | @{class:PhabricatorUserCustomField} |
|
||||||
|
| Projects | @{class:PhabricatorProjectCustomField} |
|
||||||
|
|
||||||
The easiest way to get started is to drop your subclass into
|
The easiest way to get started is to drop your subclass into
|
||||||
`phabricator/src/extensions/`, which should make it immediately available in the
|
`phabricator/src/extensions/`, which should make it immediately available in the
|
||||||
|
|
Loading…
Reference in a new issue