1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 14:52:41 +01:00

Mostly replace the old panel "Edit" controller with the new "Editpro" controller

Summary:
Depends on D20370. Ref T13272. This tries to get panel editing fully on the newer "Modular Transactions" + "EditEngine" flow.

This breaks tab panels a bit, but I'll fix that in a followup. And they weren't exactly in great shape before.

Also makes the flow prettier. :3

Test Plan: {F6332746}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13272

Differential Revision: https://secure.phabricator.com/D20371
This commit is contained in:
epriestley 2019-04-02 09:18:55 -07:00
parent 81b58dba8f
commit 68d969094f
9 changed files with 131 additions and 447 deletions

View file

@ -2933,7 +2933,6 @@ phutil_register_library_map(array(
'PhabricatorDashboardPanelEditConduitAPIMethod' => 'applications/dashboard/conduit/PhabricatorDashboardPanelEditConduitAPIMethod.php',
'PhabricatorDashboardPanelEditController' => 'applications/dashboard/controller/panel/PhabricatorDashboardPanelEditController.php',
'PhabricatorDashboardPanelEditEngine' => 'applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php',
'PhabricatorDashboardPanelEditproController' => 'applications/dashboard/controller/panel/PhabricatorDashboardPanelEditproController.php',
'PhabricatorDashboardPanelHasDashboardEdgeType' => 'applications/dashboard/edge/PhabricatorDashboardPanelHasDashboardEdgeType.php',
'PhabricatorDashboardPanelListController' => 'applications/dashboard/controller/panel/PhabricatorDashboardPanelListController.php',
'PhabricatorDashboardPanelNameTransaction' => 'applications/dashboard/xaction/panel/PhabricatorDashboardPanelNameTransaction.php',
@ -8915,7 +8914,6 @@ phutil_register_library_map(array(
'PhabricatorDashboardPanelEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'PhabricatorDashboardPanelEditController' => 'PhabricatorDashboardController',
'PhabricatorDashboardPanelEditEngine' => 'PhabricatorEditEngine',
'PhabricatorDashboardPanelEditproController' => 'PhabricatorDashboardController',
'PhabricatorDashboardPanelHasDashboardEdgeType' => 'PhabricatorEdgeType',
'PhabricatorDashboardPanelListController' => 'PhabricatorDashboardController',
'PhabricatorDashboardPanelNameTransaction' => 'PhabricatorDashboardPanelTransactionType',

View file

@ -57,10 +57,8 @@ final class PhabricatorDashboardApplication extends PhabricatorApplication {
'PhabricatorDashboardQueryPanelInstallController',
'(?:query/(?P<queryKey>[^/]+)/)?'
=> 'PhabricatorDashboardPanelListController',
'create/' => 'PhabricatorDashboardPanelEditController',
$this->getEditRoutePattern('editpro/')
=> 'PhabricatorDashboardPanelEditproController',
'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardPanelEditController',
$this->getEditRoutePattern('edit/')
=> 'PhabricatorDashboardPanelEditController',
'render/(?P<id>\d+)/' => 'PhabricatorDashboardPanelRenderController',
'archive/(?P<id>\d+)/'
=> 'PhabricatorDashboardPanelArchiveController',

View file

@ -4,351 +4,90 @@ final class PhabricatorDashboardPanelEditController
extends PhabricatorDashboardController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$viewer = $this->getViewer();
$engine = id(new PhabricatorDashboardPanelEditEngine())
->setController($this);
$id = $request->getURIData('id');
if (!$id) {
$dashboard_id = $request->getStr('dashboardID');
$column_id = $request->getStr('columnID');
// If the user is trying to create a panel directly on a dashboard, make
// sure they have permission to see and edit the dashboard.
$dashboard_id = $request->getInt('dashboardID');
$dashboard = null;
if ($dashboard_id) {
$dashboard = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withIDs(array($dashboard_id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$dashboard) {
return new Aphront404Response();
}
$manage_uri = $this->getApplicationURI('arrange/'.$dashboard_id.'/');
}
if ($id) {
$is_create = false;
if ($dashboard) {
$capabilities = array(
PhabricatorPolicyCapability::CAN_VIEW,
);
if (strlen($dashboard_id)) {
$dashboard = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withIDs(array($dashboard_id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$dashboard) {
return new Aphront404Response();
}
} else {
$capabilities = array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
$dashboard = null;
}
$panel = id(new PhabricatorDashboardPanelQuery())
->setViewer($viewer)
->withIDs(array($id))
->requireCapabilities($capabilities)
->executeOne();
if (!$panel) {
return new Aphront404Response();
}
} else {
$is_create = true;
$panel = PhabricatorDashboardPanel::initializeNewPanel($viewer);
$types = PhabricatorDashboardPanelType::getAllPanelTypes();
$type = $request->getStr('type');
if (empty($types[$type])) {
return $this->processPanelTypeRequest($request);
}
$panel->setPanelType($type);
}
if ($is_create) {
$title = pht('Create New Panel');
$button = pht('Create Panel');
$header_icon = 'fa-plus-square';
if ($dashboard) {
$cancel_uri = $manage_uri;
$cancel_uri = $dashboard->getURI();
} else {
$cancel_uri = $this->getApplicationURI('panel/');
}
} else {
$title = pht('Edit Panel: %s', $panel->getName());
$button = pht('Save Panel');
$header_icon = 'fa-pencil';
if ($dashboard) {
$cancel_uri = $manage_uri;
} else {
$cancel_uri = '/'.$panel->getMonogram();
$panel_type = $request->getStr('panelType');
$panel_types = PhabricatorDashboardPanelType::getAllPanelTypes();
if (empty($panel_types[$panel_type])) {
return $this->buildPanelTypeResponse($cancel_uri);
}
$engine
->addContextParameter('panelType', $panel_type)
->addContextParameter('dashboardID', $dashboard_id)
->addContextParameter('columnID', $column_id)
->setPanelType($panel_type)
->setDashboard($dashboard)
->setColumnID($column_id);
}
$v_name = $panel->getName();
$e_name = true;
$field_list = PhabricatorCustomField::getObjectFields(
$panel,
PhabricatorCustomField::ROLE_EDIT);
$field_list
->setViewer($viewer)
->readFieldsFromStorage($panel);
if ($is_create && !$request->isFormPost()) {
$panel->requireImplementation()->initializeFieldsFromRequest(
$panel,
$field_list,
$request);
}
$validation_exception = null;
// NOTE: We require 'edit' to distinguish between the "Choose a Type"
// and "Create a Panel" dialogs.
if ($request->isFormPost() && $request->getBool('edit')) {
$v_name = $request->getStr('name');
$v_view_policy = $request->getStr('viewPolicy');
$v_edit_policy = $request->getStr('editPolicy');
$type_name = PhabricatorDashboardPanelNameTransaction::TRANSACTIONTYPE;
$type_view_policy = PhabricatorTransactions::TYPE_VIEW_POLICY;
$type_edit_policy = PhabricatorTransactions::TYPE_EDIT_POLICY;
$xactions = array();
$xactions[] = id(new PhabricatorDashboardPanelTransaction())
->setTransactionType($type_name)
->setNewValue($v_name);
$xactions[] = id(new PhabricatorDashboardPanelTransaction())
->setTransactionType($type_view_policy)
->setNewValue($v_view_policy);
$xactions[] = id(new PhabricatorDashboardPanelTransaction())
->setTransactionType($type_edit_policy)
->setNewValue($v_edit_policy);
$field_xactions = $field_list->buildFieldTransactionsFromRequest(
new PhabricatorDashboardPanelTransaction(),
$request);
$xactions = array_merge($xactions, $field_xactions);
try {
$editor = id(new PhabricatorDashboardPanelTransactionEditor())
->setActor($viewer)
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request)
->applyTransactions($panel, $xactions);
// If we're creating a panel directly on a dashboard, add it now.
if ($dashboard && $is_create) {
PhabricatorDashboardTransactionEditor::addPanelToDashboard(
$viewer,
PhabricatorContentSource::newFromRequest($request),
$panel,
$dashboard,
$request->getInt('column', 0));
}
if ($dashboard) {
$done_uri = $manage_uri;
} else {
$done_uri = '/'.$panel->getMonogram();
}
return id(new AphrontRedirectResponse())->setURI($done_uri);
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
$e_name = $validation_exception->getShortMessage($type_name);
$panel->setViewPolicy($v_view_policy);
$panel->setEditPolicy($v_edit_policy);
}
}
// NOTE: We're setting the submit URI explicitly because we need to edit
// a different panel if we just cloned the original panel.
if ($is_create) {
$submit_uri = $this->getApplicationURI('panel/edit/');
} else {
$submit_uri = $this->getApplicationURI('panel/edit/'.$panel->getID().'/');
}
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($panel)
->execute();
$form = id(new AphrontFormView())
->setUser($viewer)
->setAction($submit_uri)
->addHiddenInput('edit', true)
->addHiddenInput('dashboardID', $request->getInt('dashboardID'))
->addHiddenInput('column', $request->getInt('column'))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Name'))
->setName('name')
->setValue($v_name)
->setError($e_name));
if (!$request->isAjax() || !$is_create) {
$form
->appendChild(
id(new AphrontFormPolicyControl())
->setName('viewPolicy')
->setPolicyObject($panel)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicies($policies))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('editPolicy')
->setPolicyObject($panel)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicies($policies));
}
$field_list->appendFieldsToForm($form);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
pht('Panels'),
$this->getApplicationURI('panel/'));
if ($is_create) {
$crumbs->addTextCrumb(pht('New Panel'));
$form->addHiddenInput('type', $panel->getPanelType());
} else {
$crumbs->addTextCrumb(
$panel->getMonogram(),
'/'.$panel->getMonogram());
$crumbs->addTextCrumb(pht('Edit'));
}
$crumbs->setBorder(true);
if ($request->isAjax()) {
return $this->newDialog()
->setTitle($title)
->setSubmitURI($submit_uri)
->setWidth(AphrontDialogView::WIDTH_FORM)
->setValidationException($validation_exception)
->appendChild($form->buildLayoutView())
->addCancelButton($cancel_uri)
->addSubmitButton($button);
} else {
$form
->appendChild(
id(new AphrontFormSubmitControl())
->setValue($button)
->addCancelButton($cancel_uri));
}
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Panel'))
->setValidationException($validation_exception)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setForm($form);
$header = id(new PHUIHeaderView())
->setHeader($title)
->setHeaderIcon($header_icon);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter($box);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
return $engine->buildResponse();
}
private function processPanelTypeRequest(AphrontRequest $request) {
$viewer = $request->getUser();
private function buildPanelTypeResponse($cancel_uri) {
$viewer = $this->getViewer();
$request = $this->getRequest();
$types = PhabricatorDashboardPanelType::getAllPanelTypes();
$base_uri = $request->getRequestURI();
$base_uri = new PhutilURI($base_uri);
$v_type = null;
$errors = array();
if ($request->isFormPost()) {
$v_type = $request->getStr('type');
if (!isset($types[$v_type])) {
$errors[] = pht('You must select a type of panel to create.');
}
$menu = id(new PHUIObjectItemListView())
->setViewer($viewer)
->setFlush(true)
->setBig(true);
$panel_types = PhabricatorDashboardPanelType::getAllPanelTypes();
foreach ($panel_types as $panel_type) {
$item = id(new PHUIObjectItemView())
->setClickable(true)
->setImageIcon($panel_type->getIcon())
->setHeader($panel_type->getPanelTypeName())
->addAttribute($panel_type->getPanelTypeDescription());
$type_uri = id(clone $base_uri)
->replaceQueryParam('panelType', $panel_type->getPanelTypeKey());
$item->setHref($type_uri);
$menu->addItem($item);
}
$cancel_uri = $this->getApplicationURI('panel/');
if (!$v_type) {
$v_type = key($types);
}
$panel_types = id(new AphrontFormRadioButtonControl())
->setName('type')
->setValue($v_type);
foreach ($types as $key => $type) {
$panel_types->addButton(
$key,
$type->getPanelTypeName(),
$type->getPanelTypeDescription());
}
$form = id(new AphrontFormView())
->setUser($viewer)
->addHiddenInput('dashboardID', $request->getInt('dashboardID'))
->addHiddenInput('column', $request->getInt('column'))
->appendRemarkupInstructions(
pht(
'Choose the type of dashboard panel to create:'))
->appendChild($panel_types);
if ($request->isAjax()) {
return $this->newDialog()
->setTitle(pht('Add New Panel'))
->setWidth(AphrontDialogView::WIDTH_FORM)
->setErrors($errors)
->appendChild($form->buildLayoutView())
->addCancelbutton($cancel_uri)
->addSubmitButton(pht('Continue'));
} else {
$form->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Continue'))
->addCancelButton($cancel_uri));
}
$title = pht('Create Dashboard Panel');
$header_icon = 'fa-plus-square';
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
pht('Panels'),
$this->getApplicationURI('panel/'));
$crumbs->addTextCrumb(pht('New Panel'));
$crumbs->setBorder(true);
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Panel'))
->setFormErrors($errors)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setForm($form);
$header = id(new PHUIHeaderView())
->setHeader($title)
->setHeaderIcon($header_icon);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter($box);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
return $this->newDialog()
->setTitle(pht('Choose Panel Type'))
->setWidth(AphrontDialogView::WIDTH_FORM)
->appendChild($menu)
->addCancelButton($cancel_uri);
}
}

View file

@ -1,105 +0,0 @@
<?php
final class PhabricatorDashboardPanelEditproController
extends PhabricatorDashboardController {
public function handleRequest(AphrontRequest $request) {
$engine = id(new PhabricatorDashboardPanelEditEngine())
->setController($this);
$id = $request->getURIData('id');
if (!$id) {
$list_uri = $this->getApplicationURI('panel/');
$panel_type = $request->getStr('panelType');
$panel_types = PhabricatorDashboardPanelType::getAllPanelTypes();
if (empty($panel_types[$panel_type])) {
return $this->buildPanelTypeResponse($list_uri);
}
$engine
->addContextParameter('panelType', $panel_type)
->setPanelType($panel_type);
}
return $engine->buildResponse();
}
private function buildPanelTypeResponse($cancel_uri) {
$panel_types = PhabricatorDashboardPanelType::getAllPanelTypes();
$viewer = $this->getViewer();
$request = $this->getRequest();
$e_type = null;
$errors = array();
if ($request->isFormPost()) {
$e_type = pht('Required');
$errors[] = pht(
'To create a new dashboard panel, you must select a panel type.');
}
$type_control = id(new AphrontFormRadioButtonControl())
->setLabel(pht('Panel Type'))
->setName('panelType')
->setError($e_type);
foreach ($panel_types as $key => $type) {
$type_control->addButton(
$key,
$type->getPanelTypeName(),
$type->getPanelTypeDescription());
}
$form = id(new AphrontFormView())
->setUser($viewer)
->appendRemarkupInstructions(
pht('Choose the type of dashboard panel to create:'))
->appendChild($type_control);
if ($request->isAjax()) {
return $this->newDialog()
->setTitle(pht('Add New Panel'))
->setWidth(AphrontDialogView::WIDTH_FORM)
->setErrors($errors)
->appendForm($form)
->addCancelButton($cancel_uri)
->addSubmitButton(pht('Continue'));
}
$form->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Continue'))
->addCancelButton($cancel_uri));
$title = pht('Create Dashboard Panel');
$header_icon = 'fa-plus-square';
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
pht('Panels'),
$this->getApplicationURI('panel/'));
$crumbs->addTextCrumb(pht('New Panel'));
$crumbs->setBorder(true);
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Panel'))
->setFormErrors($errors)
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setForm($form);
$header = id(new PHUIHeaderView())
->setHeader($title)
->setHeaderIcon($header_icon);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter($box);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
}

View file

@ -43,7 +43,7 @@ final class PhabricatorDashboardPanelListController
id(new PHUIListItemView())
->setIcon('fa-plus-square')
->setName(pht('Create Panel'))
->setHref($this->getApplicationURI().'panel/create/'));
->setHref($this->getApplicationURI().'panel/edit/'));
return $crumbs;
}
@ -52,7 +52,7 @@ final class PhabricatorDashboardPanelListController
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create a Panel'))
->setHref('/dashboard/panel/create/')
->setHref('/dashboard/panel/edit/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();

View file

@ -6,6 +6,8 @@ final class PhabricatorDashboardPanelEditEngine
const ENGINECONST = 'dashboard.panel';
private $panelType;
private $dashboard;
private $columnID;
public function setPanelType($panel_type) {
$this->panelType = $panel_type;
@ -16,6 +18,24 @@ final class PhabricatorDashboardPanelEditEngine
return $this->panelType;
}
public function setDashboard(PhabricatorDashboard $dashboard) {
$this->dashboard = $dashboard;
return $this;
}
public function getDashboard() {
return $this->dashboard;
}
public function setColumnID($column_id) {
$this->columnID = $column_id;
return $this;
}
public function getColumnID() {
return $this->columnID;
}
public function isEngineConfigurable() {
return false;
}
@ -63,6 +83,24 @@ final class PhabricatorDashboardPanelEditEngine
return pht('Create Panel');
}
protected function getObjectCreateCancelURI($object) {
$dashboard = $this->getDashboard();
if ($dashboard) {
return $dashboard->getURI();
}
return parent::getObjectCreateCancelURI($object);
}
public function getEffectiveObjectEditDoneURI($object) {
$dashboard = $this->getDashboard();
if ($dashboard) {
return $dashboard->getURI();
}
return parent::getEffectiveObjectDoneURI($object);
}
protected function getObjectEditTitleText($object) {
return pht('Edit Panel: %s', $object->getName());
}
@ -83,6 +121,22 @@ final class PhabricatorDashboardPanelEditEngine
return $object->getURI();
}
protected function didApplyTransactions($object, array $xactions) {
$dashboard = $this->getDashboard();
if ($dashboard) {
$viewer = $this->getViewer();
$controller = $this->getController();
$request = $controller->getRequest();
PhabricatorDashboardTransactionEditor::addPanelToDashboard(
$viewer,
PhabricatorContentSource::newFromRequest($request),
$object,
$dashboard,
(int)$this->getColumnID());
}
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())

View file

@ -112,12 +112,12 @@ final class PhabricatorDashboardRenderingEngine extends Phobject {
private function renderAddPanelUI($column) {
$dashboard_id = $this->dashboard->getID();
$create_uri = id(new PhutilURI('/dashboard/panel/create/'))
$create_uri = id(new PhutilURI('/dashboard/panel/edit/'))
->replaceQueryParam('dashboardID', $dashboard_id)
->replaceQueryParam('column', $column);
->replaceQueryParam('columnID', $column);
$add_uri = id(new PhutilURI('/dashboard/addpanel/'.$dashboard_id.'/'))
->replaceQueryParam('column', $column);
->replaceQueryParam('columnID', $column);
$create_button = id(new PHUIButtonView())
->setTag('a')

View file

@ -12,7 +12,7 @@ final class PhabricatorDashboardTabsPanelType
}
public function getIcon() {
return 'fa-window-maximize';
return 'fa-columns';
}
public function getPanelTypeDescription() {

View file

@ -12,13 +12,13 @@ final class PhabricatorDashboardTextPanelType
}
public function getIcon() {
return 'fa-paragraph';
return 'fa-file-text-o';
}
public function getPanelTypeDescription() {
return pht(
'Add some static text to the dashboard. This can be used to '.
'provide instructions or context.');
'Add a text panel to the dashboard to provide instructions or '.
'context.');
}
public function getFieldSpecifications() {