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

Allow projects to be quickly added from the Maniphest task creation interface

Summary:
Provide a quick workflow for adding a new project. This ended up being sort of
complicated because we don't currently put forms in dialogs. I separated the
actual <form /> tag out of the display/layout of AphrontFormView to enable this
(the dialog is itself a form).

Limitations: if you create a new project and then remove it, it won't appear in
the tokenizer until you reload the page. We need to add the ability for the
datasource to drop its cache to enable this, which is super complicated.

Test Plan:
Used "Create new project" to add a new project when creating a task.

Reviewed By: aran
Reviewers: jungejason, tuomaspelkonen, aran
CC: anjali, aran, epriestley
Differential Revision: 422
This commit is contained in:
epriestley 2011-06-09 15:28:29 -07:00
parent d710fc097f
commit eab768f705
18 changed files with 366 additions and 68 deletions

View file

@ -36,7 +36,7 @@ celerity_register_resource_map(array(
), ),
'aphront-dialog-view-css' => 'aphront-dialog-view-css' =>
array( array(
'uri' => '/res/79613f9b/rsrc/css/aphront/dialog-view.css', 'uri' => '/res/61a58113/rsrc/css/aphront/dialog-view.css',
'type' => 'css', 'type' => 'css',
'requires' => 'requires' =>
array( array(
@ -45,7 +45,7 @@ celerity_register_resource_map(array(
), ),
'aphront-error-view-css' => 'aphront-error-view-css' =>
array( array(
'uri' => '/res/98c5fc69/rsrc/css/aphront/error-view.css', 'uri' => '/res/e4c5e4ed/rsrc/css/aphront/error-view.css',
'type' => 'css', 'type' => 'css',
'requires' => 'requires' =>
array( array(
@ -54,7 +54,7 @@ celerity_register_resource_map(array(
), ),
'aphront-form-view-css' => 'aphront-form-view-css' =>
array( array(
'uri' => '/res/38a347da/rsrc/css/aphront/form-view.css', 'uri' => '/res/8ee16aba/rsrc/css/aphront/form-view.css',
'type' => 'css', 'type' => 'css',
'requires' => 'requires' =>
array( array(
@ -161,16 +161,6 @@ celerity_register_resource_map(array(
), ),
'disk' => '/rsrc/css/application/differential/core.css', 'disk' => '/rsrc/css/application/differential/core.css',
), ),
0 =>
array(
'uri' => '/res/39de799e/rsrc/js/javelin/docs/Base.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/docs/Base.js',
),
'differential-inline-comment-editor' => 'differential-inline-comment-editor' =>
array( array(
'uri' => '/res/5e4f0aa4/rsrc/js/application/differential/DifferentialInlineCommentEditor.js', 'uri' => '/res/5e4f0aa4/rsrc/js/application/differential/DifferentialInlineCommentEditor.js',
@ -305,7 +295,7 @@ celerity_register_resource_map(array(
), ),
'javelin-behavior-aphront-basic-tokenizer' => 'javelin-behavior-aphront-basic-tokenizer' =>
array( array(
'uri' => '/res/bce3961b/rsrc/js/application/core/behavior-tokenizer.js', 'uri' => '/res/5e183bd5/rsrc/js/application/core/behavior-tokenizer.js',
'type' => 'js', 'type' => 'js',
'requires' => 'requires' =>
array( array(
@ -314,6 +304,7 @@ celerity_register_resource_map(array(
2 => 'javelin-tokenizer', 2 => 'javelin-tokenizer',
3 => 'javelin-typeahead-preloaded-source', 3 => 'javelin-typeahead-preloaded-source',
4 => 'javelin-dom', 4 => 'javelin-dom',
5 => 'javelin-stratcom',
), ),
'disk' => '/rsrc/js/application/core/behavior-tokenizer.js', 'disk' => '/rsrc/js/application/core/behavior-tokenizer.js',
), ),
@ -344,7 +335,7 @@ celerity_register_resource_map(array(
), ),
'javelin-behavior-countdown-timer' => 'javelin-behavior-countdown-timer' =>
array( array(
'uri' => '/res/48477cc8/rsrc/js/application/countdown/timer.js', 'uri' => '/res/9eef8193/rsrc/js/application/countdown/timer.js',
'type' => 'js', 'type' => 'js',
'requires' => 'requires' =>
array( array(
@ -535,6 +526,19 @@ celerity_register_resource_map(array(
), ),
'disk' => '/rsrc/js/application/herald/herald-rule-editor.js', 'disk' => '/rsrc/js/application/herald/herald-rule-editor.js',
), ),
'javelin-behavior-maniphest-project-create' =>
array(
'uri' => '/res/85a0eaf9/rsrc/js/application/maniphest/behavior-project-create.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-workflow',
),
'disk' => '/rsrc/js/application/maniphest/behavior-project-create.js',
),
'javelin-behavior-maniphest-transaction-controls' => 'javelin-behavior-maniphest-transaction-controls' =>
array( array(
'uri' => '/res/94a2a395/rsrc/js/application/maniphest/behavior-transaction-controls.js', 'uri' => '/res/94a2a395/rsrc/js/application/maniphest/behavior-transaction-controls.js',
@ -586,6 +590,16 @@ celerity_register_resource_map(array(
), ),
'disk' => '/rsrc/js/application/owners/owners-path-editor.js', 'disk' => '/rsrc/js/application/owners/owners-path-editor.js',
), ),
0 =>
array(
'uri' => '/res/39de799e/rsrc/js/javelin/docs/Base.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/docs/Base.js',
),
'javelin-behavior-phabricator-keyboard-shortcuts' => 'javelin-behavior-phabricator-keyboard-shortcuts' =>
array( array(
'uri' => '/res/5a23bcc8/rsrc/js/application/core/behavior-keyboard-shortcuts.js', 'uri' => '/res/5a23bcc8/rsrc/js/application/core/behavior-keyboard-shortcuts.js',
@ -1081,6 +1095,30 @@ celerity_register_resource_map(array(
), array ( ), array (
'packages' => 'packages' =>
array ( array (
'01052905' =>
array (
'name' => 'core.pkg.css',
'symbols' =>
array (
0 => 'phabricator-core-css',
1 => 'phabricator-core-buttons-css',
2 => 'phabricator-standard-page-view',
3 => 'aphront-dialog-view-css',
4 => 'aphront-form-view-css',
5 => 'aphront-panel-view-css',
6 => 'aphront-side-nav-view-css',
7 => 'aphront-table-view-css',
8 => 'aphront-crumbs-view-css',
9 => 'aphront-tokenizer-control-css',
10 => 'aphront-typeahead-control-css',
11 => 'aphront-list-filter-view-css',
12 => 'phabricator-directory-css',
13 => 'phabricator-remarkup-css',
14 => 'syntax-highlighting-css',
),
'uri' => '/res/pkg/01052905/core.pkg.css',
'type' => 'css',
),
'03ef179e' => '03ef179e' =>
array ( array (
'name' => 'diffusion.pkg.css', 'name' => 'diffusion.pkg.css',
@ -1108,7 +1146,7 @@ celerity_register_resource_map(array(
'uri' => '/res/pkg/0e6e36aa/differential.pkg.css', 'uri' => '/res/pkg/0e6e36aa/differential.pkg.css',
'type' => 'css', 'type' => 'css',
), ),
'33f413ef' => '2892314d' =>
array ( array (
'name' => 'typeahead.pkg.js', 'name' => 'typeahead.pkg.js',
'symbols' => 'symbols' =>
@ -1121,7 +1159,7 @@ celerity_register_resource_map(array(
5 => 'javelin-tokenizer', 5 => 'javelin-tokenizer',
6 => 'javelin-behavior-aphront-basic-tokenizer', 6 => 'javelin-behavior-aphront-basic-tokenizer',
), ),
'uri' => '/res/pkg/33f413ef/typeahead.pkg.js', 'uri' => '/res/pkg/2892314d/typeahead.pkg.js',
'type' => 'js', 'type' => 'js',
), ),
'c8f4dac5' => 'c8f4dac5' =>
@ -1140,30 +1178,6 @@ celerity_register_resource_map(array(
'uri' => '/res/pkg/c8f4dac5/workflow.pkg.js', 'uri' => '/res/pkg/c8f4dac5/workflow.pkg.js',
'type' => 'js', 'type' => 'js',
), ),
'ca51195b' =>
array (
'name' => 'core.pkg.css',
'symbols' =>
array (
0 => 'phabricator-core-css',
1 => 'phabricator-core-buttons-css',
2 => 'phabricator-standard-page-view',
3 => 'aphront-dialog-view-css',
4 => 'aphront-form-view-css',
5 => 'aphront-panel-view-css',
6 => 'aphront-side-nav-view-css',
7 => 'aphront-table-view-css',
8 => 'aphront-crumbs-view-css',
9 => 'aphront-tokenizer-control-css',
10 => 'aphront-typeahead-control-css',
11 => 'aphront-list-filter-view-css',
12 => 'phabricator-directory-css',
13 => 'phabricator-remarkup-css',
14 => 'syntax-highlighting-css',
),
'uri' => '/res/pkg/ca51195b/core.pkg.css',
'type' => 'css',
),
'da416e1c' => 'da416e1c' =>
array ( array (
'name' => 'differential.pkg.js', 'name' => 'differential.pkg.js',
@ -1200,15 +1214,15 @@ celerity_register_resource_map(array(
), ),
'reverse' => 'reverse' =>
array ( array (
'aphront-crumbs-view-css' => 'ca51195b', 'aphront-crumbs-view-css' => '01052905',
'aphront-dialog-view-css' => 'ca51195b', 'aphront-dialog-view-css' => '01052905',
'aphront-form-view-css' => 'ca51195b', 'aphront-form-view-css' => '01052905',
'aphront-list-filter-view-css' => 'ca51195b', 'aphront-list-filter-view-css' => '01052905',
'aphront-panel-view-css' => 'ca51195b', 'aphront-panel-view-css' => '01052905',
'aphront-side-nav-view-css' => 'ca51195b', 'aphront-side-nav-view-css' => '01052905',
'aphront-table-view-css' => 'ca51195b', 'aphront-table-view-css' => '01052905',
'aphront-tokenizer-control-css' => 'ca51195b', 'aphront-tokenizer-control-css' => '01052905',
'aphront-typeahead-control-css' => 'ca51195b', 'aphront-typeahead-control-css' => '01052905',
'differential-changeset-view-css' => '0e6e36aa', 'differential-changeset-view-css' => '0e6e36aa',
'differential-core-view-css' => '0e6e36aa', 'differential-core-view-css' => '0e6e36aa',
'differential-revision-add-comment-css' => '0e6e36aa', 'differential-revision-add-comment-css' => '0e6e36aa',
@ -1219,7 +1233,7 @@ celerity_register_resource_map(array(
'differential-table-of-contents-css' => '0e6e36aa', 'differential-table-of-contents-css' => '0e6e36aa',
'diffusion-commit-view-css' => '03ef179e', 'diffusion-commit-view-css' => '03ef179e',
'javelin-behavior' => 'db95a6d0', 'javelin-behavior' => 'db95a6d0',
'javelin-behavior-aphront-basic-tokenizer' => '33f413ef', 'javelin-behavior-aphront-basic-tokenizer' => '2892314d',
'javelin-behavior-aphront-form-disable-on-submit' => 'c8f4dac5', 'javelin-behavior-aphront-form-disable-on-submit' => 'c8f4dac5',
'javelin-behavior-differential-diff-radios' => 'da416e1c', 'javelin-behavior-differential-diff-radios' => 'da416e1c',
'javelin-behavior-differential-edit-inline-comments' => 'da416e1c', 'javelin-behavior-differential-edit-inline-comments' => 'da416e1c',
@ -1235,23 +1249,23 @@ celerity_register_resource_map(array(
'javelin-mask' => 'c8f4dac5', 'javelin-mask' => 'c8f4dac5',
'javelin-request' => 'db95a6d0', 'javelin-request' => 'db95a6d0',
'javelin-stratcom' => 'db95a6d0', 'javelin-stratcom' => 'db95a6d0',
'javelin-tokenizer' => '33f413ef', 'javelin-tokenizer' => '2892314d',
'javelin-typeahead' => '33f413ef', 'javelin-typeahead' => '2892314d',
'javelin-typeahead-normalizer' => '33f413ef', 'javelin-typeahead-normalizer' => '2892314d',
'javelin-typeahead-ondemand-source' => '33f413ef', 'javelin-typeahead-ondemand-source' => '2892314d',
'javelin-typeahead-preloaded-source' => '33f413ef', 'javelin-typeahead-preloaded-source' => '2892314d',
'javelin-typeahead-source' => '33f413ef', 'javelin-typeahead-source' => '2892314d',
'javelin-uri' => 'db95a6d0', 'javelin-uri' => 'db95a6d0',
'javelin-util' => 'db95a6d0', 'javelin-util' => 'db95a6d0',
'javelin-vector' => 'db95a6d0', 'javelin-vector' => 'db95a6d0',
'javelin-workflow' => 'c8f4dac5', 'javelin-workflow' => 'c8f4dac5',
'phabricator-core-buttons-css' => 'ca51195b', 'phabricator-core-buttons-css' => '01052905',
'phabricator-core-css' => 'ca51195b', 'phabricator-core-css' => '01052905',
'phabricator-directory-css' => 'ca51195b', 'phabricator-directory-css' => '01052905',
'phabricator-keyboard-shortcut' => 'c8f4dac5', 'phabricator-keyboard-shortcut' => 'c8f4dac5',
'phabricator-keyboard-shortcut-manager' => 'c8f4dac5', 'phabricator-keyboard-shortcut-manager' => 'c8f4dac5',
'phabricator-remarkup-css' => 'ca51195b', 'phabricator-remarkup-css' => '01052905',
'phabricator-standard-page-view' => 'ca51195b', 'phabricator-standard-page-view' => '01052905',
'syntax-highlighting-css' => 'ca51195b', 'syntax-highlighting-css' => '01052905',
), ),
)); ));

View file

@ -30,6 +30,7 @@ phutil_register_library_map(array(
'AphrontFormDividerControl' => 'view/form/control/divider', 'AphrontFormDividerControl' => 'view/form/control/divider',
'AphrontFormDragAndDropUploadControl' => 'view/form/control/draganddropupload', 'AphrontFormDragAndDropUploadControl' => 'view/form/control/draganddropupload',
'AphrontFormFileControl' => 'view/form/control/file', 'AphrontFormFileControl' => 'view/form/control/file',
'AphrontFormLayoutView' => 'view/form/layout',
'AphrontFormMarkupControl' => 'view/form/control/markup', 'AphrontFormMarkupControl' => 'view/form/control/markup',
'AphrontFormPasswordControl' => 'view/form/control/password', 'AphrontFormPasswordControl' => 'view/form/control/password',
'AphrontFormRecaptchaControl' => 'view/form/control/recaptcha', 'AphrontFormRecaptchaControl' => 'view/form/control/recaptcha',
@ -426,6 +427,7 @@ phutil_register_library_map(array(
'PhabricatorProjectListController' => 'applications/project/controller/list', 'PhabricatorProjectListController' => 'applications/project/controller/list',
'PhabricatorProjectProfile' => 'applications/project/storage/profile', 'PhabricatorProjectProfile' => 'applications/project/storage/profile',
'PhabricatorProjectProfileController' => 'applications/project/controller/profile', 'PhabricatorProjectProfileController' => 'applications/project/controller/profile',
'PhabricatorProjectQuickCreateController' => 'applications/project/controller/quickcreate',
'PhabricatorRedirectController' => 'applications/base/controller/redirect', 'PhabricatorRedirectController' => 'applications/base/controller/redirect',
'PhabricatorRemarkupRuleDifferential' => 'infrastructure/markup/remarkup/markuprule/differential', 'PhabricatorRemarkupRuleDifferential' => 'infrastructure/markup/remarkup/markuprule/differential',
'PhabricatorRemarkupRuleDiffusion' => 'infrastructure/markup/remarkup/markuprule/diffusion', 'PhabricatorRemarkupRuleDiffusion' => 'infrastructure/markup/remarkup/markuprule/diffusion',
@ -570,6 +572,7 @@ phutil_register_library_map(array(
'AphrontFormDividerControl' => 'AphrontFormControl', 'AphrontFormDividerControl' => 'AphrontFormControl',
'AphrontFormDragAndDropUploadControl' => 'AphrontFormControl', 'AphrontFormDragAndDropUploadControl' => 'AphrontFormControl',
'AphrontFormFileControl' => 'AphrontFormControl', 'AphrontFormFileControl' => 'AphrontFormControl',
'AphrontFormLayoutView' => 'AphrontView',
'AphrontFormMarkupControl' => 'AphrontFormControl', 'AphrontFormMarkupControl' => 'AphrontFormControl',
'AphrontFormPasswordControl' => 'AphrontFormControl', 'AphrontFormPasswordControl' => 'AphrontFormControl',
'AphrontFormRecaptchaControl' => 'AphrontFormControl', 'AphrontFormRecaptchaControl' => 'AphrontFormControl',
@ -881,6 +884,7 @@ phutil_register_library_map(array(
'PhabricatorProjectListController' => 'PhabricatorProjectController', 'PhabricatorProjectListController' => 'PhabricatorProjectController',
'PhabricatorProjectProfile' => 'PhabricatorProjectDAO', 'PhabricatorProjectProfile' => 'PhabricatorProjectDAO',
'PhabricatorProjectProfileController' => 'PhabricatorProjectController', 'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
'PhabricatorProjectQuickCreateController' => 'PhabricatorProjectController',
'PhabricatorRedirectController' => 'PhabricatorController', 'PhabricatorRedirectController' => 'PhabricatorController',
'PhabricatorRemarkupRuleDifferential' => 'PhabricatorRemarkupRuleObjectName', 'PhabricatorRemarkupRuleDifferential' => 'PhabricatorRemarkupRuleObjectName',
'PhabricatorRemarkupRuleDiffusion' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleDiffusion' => 'PhutilRemarkupRule',

View file

@ -200,6 +200,7 @@ class AphrontDefaultApplicationConfiguration
'view/(?P<id>\d+)/$' => 'PhabricatorProjectProfileController', 'view/(?P<id>\d+)/$' => 'PhabricatorProjectProfileController',
'affiliation/(?P<id>\d+)/$' 'affiliation/(?P<id>\d+)/$'
=> 'PhabricatorProjectAffiliationEditController', => 'PhabricatorProjectAffiliationEditController',
'quickcreate/$' => 'PhabricatorProjectQuickCreateController',
), ),
'/r(?P<callsign>[A-Z]+)(?P<commit>[a-z0-9]+)$' '/r(?P<callsign>[A-Z]+)(?P<commit>[a-z0-9]+)$'

View file

@ -210,6 +210,8 @@ class ManiphestTaskEditController extends ManiphestController {
$header_name = 'Create New Task'; $header_name = 'Create New Task';
} }
$project_tokenizer_id = celerity_generate_unique_node_id();
$form = new AphrontFormView(); $form = new AphrontFormView();
$form $form
->setUser($user) ->setUser($user)
@ -245,8 +247,22 @@ class ManiphestTaskEditController extends ManiphestController {
->setLabel('Projects') ->setLabel('Projects')
->setName('projects') ->setName('projects')
->setValue($projects_value) ->setValue($projects_value)
->setID($project_tokenizer_id)
->setCaption(
javelin_render_tag(
'a',
array(
'href' => '/project/quickcreate/',
'mustcapture' => true,
'sigil' => 'project-create',
),
'Create New Project'))
->setDatasource('/typeahead/common/projects/')); ->setDatasource('/typeahead/common/projects/'));
Javelin::initBehavior('maniphest-project-create', array(
'tokenizerID' => $project_tokenizer_id,
));
if ($files) { if ($files) {
$file_display = array(); $file_display = array();
foreach ($files as $file) { foreach ($files as $file) {

View file

@ -18,6 +18,9 @@ phutil_require_module('phabricator', 'applications/maniphest/storage/task');
phutil_require_module('phabricator', 'applications/maniphest/storage/transaction'); phutil_require_module('phabricator', 'applications/maniphest/storage/transaction');
phutil_require_module('phabricator', 'applications/phid/constants'); phutil_require_module('phabricator', 'applications/phid/constants');
phutil_require_module('phabricator', 'applications/phid/handle/data'); phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'infrastructure/javelin/api');
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
phutil_require_module('phabricator', 'view/form/base'); phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/markup'); phutil_require_module('phabricator', 'view/form/control/markup');
phutil_require_module('phabricator', 'view/form/control/select'); phutil_require_module('phabricator', 'view/form/control/select');

View file

@ -0,0 +1,95 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class PhabricatorProjectQuickCreateController
extends PhabricatorProjectController {
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$project = new PhabricatorProject();
$project->setAuthorPHID($user->getPHID());
$profile = new PhabricatorProjectProfile();
$e_name = true;
$errors = array();
if ($request->isFormPost()) {
$project->setName($request->getStr('name'));
$profile->setBlurb($request->getStr('blurb'));
if (!strlen($project->getName())) {
$e_name = 'Required';
$errors[] = 'Project name is required.';
} else {
$e_name = null;
}
if (!$errors) {
$project->save();
$profile->setProjectPHID($project->getPHID());
$profile->save();
return id(new AphrontAjaxResponse())
->setContent(array(
'phid' => $project->getPHID(),
'name' => $project->getName(),
));
}
}
$error_view = null;
if ($errors) {
$error_view = new AphrontErrorView();
$error_view->setTitle('Form Errors');
$error_view->setWidth(AphrontErrorView::WIDTH_DIALOG);
$error_view->setErrors($errors);
}
$form = id(new AphrontFormLayoutView())
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Name')
->setName('name')
->setValue($project->getName())
->setError($e_name))
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Blurb')
->setName('blurb')
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
->setValue($profile->getBlurb()));
$dialog = id(new AphrontDialogView())
->setUser($user)
->setWidth(AphrontDialogView::WIDTH_FORM)
->setTitle('Create a New Project')
->appendChild($error_view)
->appendChild($form)
->addSubmitButton('Create Project')
->addCancelButton('/project/');
return id(new AphrontDialogResponse())->setDialog($dialog);
}
}

View file

@ -0,0 +1,23 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/ajax');
phutil_require_module('phabricator', 'aphront/response/dialog');
phutil_require_module('phabricator', 'applications/project/controller/base');
phutil_require_module('phabricator', 'applications/project/storage/profile');
phutil_require_module('phabricator', 'applications/project/storage/project');
phutil_require_module('phabricator', 'view/dialog');
phutil_require_module('phabricator', 'view/form/control/text');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/form/layout');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorProjectQuickCreateController.php');

View file

@ -29,6 +29,10 @@ class AphrontDialogView extends AphrontView {
private $renderAsForm = true; private $renderAsForm = true;
private $formID; private $formID;
private $width = 'default';
const WIDTH_DEFAULT = 'default';
const WIDTH_FORM = 'form';
public function setUser(PhabricatorUser $user) { public function setUser(PhabricatorUser $user) {
$this->user = $user; $this->user = $user;
return $this; return $this;
@ -80,6 +84,11 @@ class AphrontDialogView extends AphrontView {
return $this; return $this;
} }
public function setWidth($width) {
$this->width = $width;
return $this;
}
final public function render() { final public function render() {
require_celerity_resource('aphront-dialog-view-css'); require_celerity_resource('aphront-dialog-view-css');
@ -114,6 +123,16 @@ class AphrontDialogView extends AphrontView {
$more = $this->class; $more = $this->class;
switch ($this->width) {
case self::WIDTH_FORM:
$more .= ' aphront-dialog-view-width-'.$this->width;
break;
case self::WIDTH_DEFAULT:
break;
default:
throw new Exception("Unknown dialog width '{$this->width}'!");
}
$attributes = array( $attributes = array(
'class' => 'aphront-dialog-view '.$more, 'class' => 'aphront-dialog-view '.$more,
'sigil' => 'jx-dialog', 'sigil' => 'jx-dialog',

View file

@ -67,18 +67,22 @@ final class AphrontFormView extends AphrontView {
Javelin::initBehavior('aphront-form-disable-on-submit'); Javelin::initBehavior('aphront-form-disable-on-submit');
$layout = id(new AphrontFormLayoutView())
->setBackgroundShading(true)
->setPadded(true)
->appendChild($this->renderDataInputs())
->appendChild($this->renderChildren());
return javelin_render_tag( return javelin_render_tag(
'form', 'form',
array( array(
'action' => $this->action, 'action' => $this->action,
'method' => $this->method, 'method' => $this->method,
'class' => 'aphront-form-view',
'enctype' => $this->encType, 'enctype' => $this->encType,
'sigil' => $this->workflow ? 'workflow' : null, 'sigil' => $this->workflow ? 'workflow' : null,
'id' => $this->id, 'id' => $this->id,
), ),
$this->renderDataInputs(). $layout->render());
$this->renderChildren());
} }
private function renderDataInputs() { private function renderDataInputs() {

View file

@ -10,8 +10,10 @@ phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'infrastructure/javelin/api'); phutil_require_module('phabricator', 'infrastructure/javelin/api');
phutil_require_module('phabricator', 'infrastructure/javelin/markup'); phutil_require_module('phabricator', 'infrastructure/javelin/markup');
phutil_require_module('phabricator', 'view/base'); phutil_require_module('phabricator', 'view/base');
phutil_require_module('phabricator', 'view/form/layout');
phutil_require_module('phutil', 'markup'); phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('AphrontFormView.php'); phutil_require_source('AphrontFormView.php');

View file

@ -24,6 +24,7 @@ final class AphrontErrorView extends AphrontView {
const WIDTH_DEFAULT = 'default'; const WIDTH_DEFAULT = 'default';
const WIDTH_WIDE = 'wide'; const WIDTH_WIDE = 'wide';
const WIDTH_DIALOG = 'dialog';
private $title; private $title;
private $errors; private $errors;

View file

@ -0,0 +1,59 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This provides the layout of an AphrontFormView without actually providing
* the <form /> tag. Useful on its own for creating forms in other forms (like
* dialogs) or forms which aren't submittable.
*/
final class AphrontFormLayoutView extends AphrontView {
private $backgroundShading;
private $padded;
public function setBackgroundShading($shading) {
$this->backgroundShading = $shading;
return $this;
}
public function setPadded($padded) {
$this->padded = $padded;
return $this;
}
public function render() {
$classes = array('aphront-form-view');
if ($this->backgroundShading) {
$classes[] = 'aphront-form-view-shaded';
}
if ($this->padded) {
$classes[] = 'aphront-form-view-padded';
}
$classes = implode(' ', $classes);
return phutil_render_tag(
'div',
array(
'class' => $classes,
),
$this->renderChildren());
}
}

View file

@ -0,0 +1,14 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'view/base');
phutil_require_module('phutil', 'markup');
phutil_require_source('AphrontFormLayoutView.php');

View file

@ -17,6 +17,9 @@
color: #ffffff; color: #ffffff;
} }
.aphront-dialog-view-width-form {
width: 600px;
}
.aphront-dialog-body { .aphront-dialog-body {
background: #ffffff; background: #ffffff;

View file

@ -15,6 +15,10 @@
width: 720px; width: 720px;
} }
.aphront-error-width-dialog {
width: 300px;
}
.aphront-error-width-wide { .aphront-error-width-wide {
width: 95%; width: 95%;
} }

View file

@ -2,12 +2,19 @@
* @provides aphront-form-view-css * @provides aphront-form-view-css
*/ */
.aphront-form-view { /**
background: #e7e7e7; * These styles are overrides for .aphront-form-view
*/
.aphront-form-view-shaded {
border: 1px solid #c4c4c4; border: 1px solid #c4c4c4;
background: #e7e7e7;
}
.aphront-form-view-padded {
padding: 1em; padding: 1em;
} }
.aphront-form-view label.aphront-form-label { .aphront-form-view label.aphront-form-label {
padding-top: 4px; padding-top: 4px;
width: 19%; width: 19%;

View file

@ -5,6 +5,7 @@
* javelin-tokenizer * javelin-tokenizer
* javelin-typeahead-preloaded-source * javelin-typeahead-preloaded-source
* javelin-dom * javelin-dom
* javelin-stratcom
*/ */
JX.behavior('aphront-basic-tokenizer', function(config) { JX.behavior('aphront-basic-tokenizer', function(config) {
@ -28,5 +29,7 @@ JX.behavior('aphront-basic-tokenizer', function(config) {
tokenizer.setInitialValue(config.value); tokenizer.setInitialValue(config.value);
} }
JX.Stratcom.addData(root, {'tokenizer' : tokenizer});
tokenizer.start(); tokenizer.start();
}); });

View file

@ -0,0 +1,26 @@
/**
* @provides javelin-behavior-maniphest-project-create
* @requires javelin-behavior
* javelin-dom
* javelin-stratcom
* javelin-workflow
*/
JX.behavior('maniphest-project-create', function(config) {
JX.Stratcom.listen(
'click',
'project-create',
function(e) {
JX.Workflow.newFromLink(e.getTarget())
.setHandler(function(r) {
var node = JX.$(config.tokenizerID);
var tokenizer = JX.Stratcom.getData(node).tokenizer;
tokenizer.addToken(r.phid, r.name);
})
.start();
e.kill();
});
});