diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index aad89e08fe..d4591e4d5b 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2029,7 +2029,6 @@ phutil_register_library_map(array( 'PhabricatorProjectConfiguredCustomField' => 'applications/project/customfield/PhabricatorProjectConfiguredCustomField.php', 'PhabricatorProjectConstants' => 'applications/project/constants/PhabricatorProjectConstants.php', 'PhabricatorProjectController' => 'applications/project/controller/PhabricatorProjectController.php', - 'PhabricatorProjectCreateController' => 'applications/project/controller/PhabricatorProjectCreateController.php', 'PhabricatorProjectCustomField' => 'applications/project/customfield/PhabricatorProjectCustomField.php', 'PhabricatorProjectCustomFieldNumericIndex' => 'applications/project/storage/PhabricatorProjectCustomFieldNumericIndex.php', 'PhabricatorProjectCustomFieldStorage' => 'applications/project/storage/PhabricatorProjectCustomFieldStorage.php', @@ -5030,7 +5029,6 @@ phutil_register_library_map(array( 'PhabricatorStandardCustomFieldInterface', ), 'PhabricatorProjectController' => 'PhabricatorController', - 'PhabricatorProjectCreateController' => 'PhabricatorProjectController', 'PhabricatorProjectCustomField' => 'PhabricatorCustomField', 'PhabricatorProjectCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage', 'PhabricatorProjectCustomFieldStorage' => 'PhabricatorCustomFieldStorage', diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php index 5866a2038a..9c8a5e48d3 100644 --- a/src/applications/project/application/PhabricatorProjectApplication.php +++ b/src/applications/project/application/PhabricatorProjectApplication.php @@ -58,7 +58,9 @@ final class PhabricatorProjectApplication extends PhabricatorApplication { => 'PhabricatorProjectEditPictureController', 'icon/(?P[1-9]\d*)/' => 'PhabricatorProjectEditIconController', - 'create/' => 'PhabricatorProjectCreateController', + 'icon/' + => 'PhabricatorProjectEditIconController', + 'create/' => 'PhabricatorProjectEditDetailsController', 'board/(?P[1-9]\d*)/'. '(?Pfilter/)?'. '(?:query/(?P[^/]+)/)?' diff --git a/src/applications/project/controller/PhabricatorProjectCreateController.php b/src/applications/project/controller/PhabricatorProjectCreateController.php deleted file mode 100644 index 3b14a209f3..0000000000 --- a/src/applications/project/controller/PhabricatorProjectCreateController.php +++ /dev/null @@ -1,115 +0,0 @@ -getRequest(); - $user = $request->getUser(); - - $this->requireApplicationCapability( - ProjectCreateProjectsCapability::CAPABILITY); - - $project = PhabricatorProject::initializeNewProject($user); - - $e_name = true; - $type_name = PhabricatorProjectTransaction::TYPE_NAME; - $v_name = $project->getName(); - $validation_exception = null; - if ($request->isFormPost()) { - $xactions = array(); - $v_name = $request->getStr('name'); - - $xactions[] = id(new PhabricatorProjectTransaction()) - ->setTransactionType($type_name) - ->setNewValue($v_name); - - $xactions[] = id(new PhabricatorProjectTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', PhabricatorEdgeConfig::TYPE_PROJ_MEMBER) - ->setNewValue( - array( - '+' => array($user->getPHID() => $user->getPHID()), - )); - - $editor = id(new PhabricatorProjectTransactionEditor()) - ->setActor($user) - ->setContinueOnNoEffect(true) - ->setContentSourceFromRequest($request); - try { - $editor->applyTransactions($project, $xactions); - if ($request->isAjax()) { - return id(new AphrontAjaxResponse()) - ->setContent(array( - 'phid' => $project->getPHID(), - 'name' => $project->getName(), - )); - } else { - return id(new AphrontRedirectResponse()) - ->setURI('/project/view/'.$project->getID().'/'); - } - } catch (PhabricatorApplicationTransactionValidationException $ex) { - $validation_exception = $ex; - $e_name = $ex->getShortMessage($type_name); - } - } - - if ($request->isAjax()) { - $form = new PHUIFormLayoutView(); - } else { - $form = new AphrontFormView(); - $form->setUser($user); - } - - $form - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('Name')) - ->setName('name') - ->setValue($v_name) - ->setError($e_name)); - - if ($request->isAjax()) { - $errors = array(); - if ($validation_exception) { - $errors = mpull($ex->getErrors(), 'getMessage'); - } - $dialog = id(new AphrontDialogView()) - ->setUser($user) - ->setWidth(AphrontDialogView::WIDTH_FORM) - ->setTitle(pht('Create a New Project')) - ->setErrors($errors) - ->appendChild($form) - ->addSubmitButton(pht('Create Project')) - ->addCancelButton('/project/'); - - return id(new AphrontDialogResponse())->setDialog($dialog); - } else { - $form - ->appendChild( - id(new AphrontFormSubmitControl()) - ->setValue(pht('Create')) - ->addCancelButton('/project/')); - - $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView()); - $crumbs->addTextCrumb( - pht('Create Project'), - $this->getApplicationURI().'create/'); - - $form_box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Create New Project')) - ->setValidationException($validation_exception) - ->setForm($form); - - return $this->buildApplicationPage( - array( - $crumbs, - $form_box, - ), - array( - 'title' => pht('Create New Project'), - )); - } - } - -} diff --git a/src/applications/project/controller/PhabricatorProjectEditDetailsController.php b/src/applications/project/controller/PhabricatorProjectEditDetailsController.php index 763e79f4f0..ebba9eaa9a 100644 --- a/src/applications/project/controller/PhabricatorProjectEditDetailsController.php +++ b/src/applications/project/controller/PhabricatorProjectEditDetailsController.php @@ -6,25 +6,37 @@ final class PhabricatorProjectEditDetailsController private $id; public function willProcessRequest(array $data) { - $this->id = $data['id']; + $this->id = idx($data, 'id'); } public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); - $project = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->withIDs(array($this->id)) - ->needSlugs(true) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$project) { - return new Aphront404Response(); + if ($this->id) { + $is_new = false; + + $project = id(new PhabricatorProjectQuery()) + ->setViewer($viewer) + ->withIDs(array($this->id)) + ->needSlugs(true) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$project) { + return new Aphront404Response(); + } + + } else { + $is_new = true; + + $this->requireApplicationCapability( + ProjectCreateProjectsCapability::CAPABILITY); + + $project = PhabricatorProject::initializeNewProject($viewer); } $field_list = PhabricatorCustomField::getObjectFields( @@ -114,10 +126,37 @@ final class PhabricatorProjectEditDetailsController ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true); + if ($is_new) { + $xactions[] = id(new PhabricatorProjectTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue( + 'edge:type', + PhabricatorEdgeConfig::TYPE_PROJ_MEMBER) + ->setNewValue( + array( + '+' => array($viewer->getPHID() => $viewer->getPHID()), + )); + } + try { + $editor->applyTransactions($project, $xactions); - return id(new AphrontRedirectResponse())->setURI($edit_uri); + if ($request->isAjax()) { + return id(new AphrontAjaxResponse()) + ->setContent(array( + 'phid' => $project->getPHID(), + 'name' => $project->getName(), + )); + } + + if ($is_new) { + $redirect_uri = $view_uri; + } else { + $redirect_uri = $edit_uri; + } + + return id(new AphrontRedirectResponse())->setURI($redirect_uri); } catch (PhabricatorApplicationTransactionValidationException $ex) { $validation_exception = $ex; @@ -131,8 +170,13 @@ final class PhabricatorProjectEditDetailsController } } - $header_name = pht('Edit Project'); - $title = pht('Edit Project'); + if ($is_new) { + $header_name = pht('Create a New Project'); + $title = pht('Create Project'); + } else { + $header_name = pht('Edit Project'); + $title = pht('Edit Project'); + } $policies = id(new PhabricatorPolicyQuery()) ->setViewer($viewer) @@ -140,8 +184,7 @@ final class PhabricatorProjectEditDetailsController ->execute(); $v_slugs = implode(', ', $v_slugs); - $form = new AphrontFormView(); - $form + $form = id(new AphrontFormView()) ->setUser($viewer) ->appendChild( id(new AphrontFormTextControl()) @@ -153,7 +196,11 @@ final class PhabricatorProjectEditDetailsController $shades = PhabricatorProjectIcon::getColorMap(); - $icon_uri = $this->getApplicationURI('icon/'.$project->getID().'/'); + if ($is_new) { + $icon_uri = $this->getApplicationURI('icon/'); + } else { + $icon_uri = $this->getApplicationURI('icon/'.$project->getID().'/'); + } $icon_display = PhabricatorProjectIcon::renderIconForChooser($v_icon); list($can_lock, $lock_message) = $this->explainApplicationCapability( ProjectCanLockProjectsCapability::CAPABILITY, @@ -221,21 +268,43 @@ final class PhabricatorProjectEditDetailsController 1, pht('Prevent members from leaving this project.'), $v_locked) - ->setCaption($lock_message)) - ->appendChild( - id(new AphrontFormSubmitControl()) - ->addCancelButton($edit_uri) - ->setValue(pht('Save'))); + ->setCaption($lock_message)); + + if ($request->isAjax()) { + $errors = array(); + if ($validation_exception) { + $errors = mpull($ex->getErrors(), 'getMessage'); + } + $dialog = id(new AphrontDialogView()) + ->setUser($viewer) + ->setWidth(AphrontDialogView::WIDTH_FULL) + ->setTitle($header_name) + ->setErrors($errors) + ->appendForm($form) + ->addSubmitButton($title) + ->addCancelButton('/project/'); + return id(new AphrontDialogResponse())->setDialog($dialog); + } + + $form->appendChild( + id(new AphrontFormSubmitControl()) + ->addCancelButton($edit_uri) + ->setValue(pht('Save'))); $form_box = id(new PHUIObjectBoxView()) ->setHeaderText($title) ->setValidationException($validation_exception) ->setForm($form); - $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView()) - ->addTextCrumb($project->getName(), $view_uri) - ->addTextCrumb(pht('Edit'), $edit_uri) - ->addTextCrumb(pht('Details')); + $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView()); + if ($is_new) { + $crumbs->addTextCrumb($title); + } else { + $crumbs + ->addTextCrumb($project->getName(), $view_uri) + ->addTextCrumb(pht('Edit'), $edit_uri) + ->addTextCrumb(pht('Details')); + } return $this->buildApplicationPage( array( diff --git a/src/applications/project/controller/PhabricatorProjectEditIconController.php b/src/applications/project/controller/PhabricatorProjectEditIconController.php index c3d2b06bb8..d8fc42eaf7 100644 --- a/src/applications/project/controller/PhabricatorProjectEditIconController.php +++ b/src/applications/project/controller/PhabricatorProjectEditIconController.php @@ -6,27 +6,36 @@ final class PhabricatorProjectEditIconController private $id; public function willProcessRequest(array $data) { - $this->id = $data['id']; + $this->id = idx($data, 'id'); } public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); - $project = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->withIDs(array($this->id)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$project) { - return new Aphront404Response(); + if ($this->id) { + $project = id(new PhabricatorProjectQuery()) + ->setViewer($viewer) + ->withIDs(array($this->id)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$project) { + return new Aphront404Response(); + } + $cancel_uri = $this->getApplicationURI('edit/'.$project->getID().'/'); + $project_icon = $project->getIcon(); + } else { + $this->requireApplicationCapability( + ProjectCreateProjectsCapability::CAPABILITY); + + $cancel_uri = '/project/'; + $project_icon = $request->getStr('value'); } - $edit_uri = $this->getApplicationURI('edit/'.$project->getID().'/'); require_celerity_resource('project-icon-css'); Javelin::initBehavior('phabricator-tooltips'); @@ -55,7 +64,7 @@ final class PhabricatorProjectEditIconController ), pht('Choose "%s" Icon', $label)); - if ($icon == $project->getIcon()) { + if ($icon == $project_icon) { $class_extra = ' selected'; } else { $class_extra = null; @@ -92,6 +101,6 @@ final class PhabricatorProjectEditIconController return $this->newDialog() ->setTitle(pht('Choose Project Icon')) ->appendChild($buttons) - ->addCancelButton($edit_uri); + ->addCancelButton($cancel_uri); } } diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php index 27db584e24..e5698d744e 100644 --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -45,7 +45,8 @@ final class PhabricatorProject extends PhabricatorProjectDAO ->setEditPolicy(PhabricatorPolicies::POLICY_USER) ->setJoinPolicy(PhabricatorPolicies::POLICY_USER) ->setIsMembershipLocked(0) - ->attachMemberPHIDs(array()); + ->attachMemberPHIDs(array()) + ->attachSlugs(array()); } public function getCapabilities() { diff --git a/src/view/AphrontDialogView.php b/src/view/AphrontDialogView.php index 879999468c..878ab77109 100644 --- a/src/view/AphrontDialogView.php +++ b/src/view/AphrontDialogView.php @@ -146,6 +146,10 @@ final class AphrontDialogView extends AphrontView { $paragraph)); } + public function appendForm(AphrontFormView $form) { + return $this->appendChild($form->buildLayoutView()); + } + public function setDisableWorkflowOnSubmit($disable_workflow_on_submit) { $this->disableWorkflowOnSubmit = $disable_workflow_on_submit; return $this;