Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2893184
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
34 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/applications/maniphest/auxiliaryfield/ManiphestAuxiliaryFieldDefaultSpecification.php b/src/applications/maniphest/auxiliaryfield/ManiphestAuxiliaryFieldDefaultSpecification.php
index 8338c6dc6a..980b87967b 100644
--- a/src/applications/maniphest/auxiliaryfield/ManiphestAuxiliaryFieldDefaultSpecification.php
+++ b/src/applications/maniphest/auxiliaryfield/ManiphestAuxiliaryFieldDefaultSpecification.php
@@ -1,421 +1,424 @@
<?php
/**
* @group maniphest
*/
class ManiphestAuxiliaryFieldDefaultSpecification
extends ManiphestAuxiliaryFieldSpecification {
private $required;
private $fieldType;
private $selectOptions;
private $checkboxLabel;
private $checkboxValue;
private $error;
private $shouldCopyWhenCreatingSimilarTask;
const TYPE_SELECT = 'select';
const TYPE_STRING = 'string';
const TYPE_INT = 'int';
const TYPE_BOOL = 'bool';
const TYPE_DATE = 'date';
const TYPE_REMARKUP = 'remarkup';
const TYPE_USER = 'user';
const TYPE_USERS = 'users';
const TYPE_HEADER = 'header';
public function getFieldType() {
return $this->fieldType;
}
public function setFieldType($val) {
$this->fieldType = $val;
return $this;
}
public function getError() {
return $this->error;
}
public function setError($val) {
$this->error = $val;
return $this;
}
public function getSelectOptions() {
return $this->selectOptions;
}
public function setSelectOptions($array) {
$this->selectOptions = $array;
return $this;
}
public function setRequired($bool) {
$this->required = $bool;
return $this;
}
public function isRequired() {
return $this->required;
}
public function setCheckboxLabel($checkbox_label) {
$this->checkboxLabel = $checkbox_label;
return $this;
}
public function getCheckboxLabel() {
return $this->checkboxLabel;
}
public function setCheckboxValue($checkbox_value) {
$this->checkboxValue = $checkbox_value;
return $this;
}
public function getCheckboxValue() {
return $this->checkboxValue;
}
public function renderControl() {
$control = null;
$type = $this->getFieldType();
switch ($type) {
case self::TYPE_INT:
$control = new AphrontFormTextControl();
break;
case self::TYPE_STRING:
$control = new AphrontFormTextControl();
break;
case self::TYPE_SELECT:
$control = new AphrontFormSelectControl();
$control->setOptions($this->getSelectOptions());
break;
case self::TYPE_BOOL:
$control = new AphrontFormCheckboxControl();
break;
case self::TYPE_DATE:
$control = new AphrontFormDateControl();
$control->setUser($this->getUser());
+ if (!$this->isRequired()) {
+ $control->setAllowNull(true);
+ }
break;
case self::TYPE_REMARKUP:
$control = new PhabricatorRemarkupControl();
$control->setUser($this->getUser());
break;
case self::TYPE_USER:
case self::TYPE_USERS:
$control = new AphrontFormTokenizerControl();
$control->setDatasource('/typeahead/common/users/');
if ($type == self::TYPE_USER) {
$control->setLimit(1);
}
break;
case self::TYPE_HEADER:
$control = new AphrontFormMarkupControl();
break;
default:
$label = $this->getLabel();
throw new ManiphestAuxiliaryFieldTypeException(
"Field type '{$type}' is not a valid type (for field '{$label}').");
break;
}
switch ($type) {
case self::TYPE_BOOL:
$control->addCheckbox(
'auxiliary['.$this->getAuxiliaryKey().']',
1,
$this->getCheckboxLabel(),
(bool)$this->getValue());
break;
case self::TYPE_DATE:
- $control->setValue($this->getValue());
+ if ($this->getValue() > 0) {
+ $control->setValue($this->getValue());
+ }
$control->setName('auxiliary_date_'.$this->getAuxiliaryKey());
break;
case self::TYPE_USER:
case self::TYPE_USERS:
$control->setName('auxiliary_tokenizer_'.$this->getAuxiliaryKey());
$value = array();
foreach ($this->getValue() as $phid) {
$value[$phid] = $this->getHandle($phid)->getFullName();
}
$control->setValue($value);
break;
case self::TYPE_HEADER:
$control->setValue(
phutil_tag(
'h2',
array(
'class' => 'maniphest-auxiliary-header',
),
$this->getLabel()));
break;
default:
$control->setValue($this->getValue());
$control->setName('auxiliary['.$this->getAuxiliaryKey().']');
break;
}
switch ($type) {
case self::TYPE_HEADER:
break;
default:
$control->setLabel($this->getLabel());
$control->setCaption($this->getCaption());
$control->setError($this->getError());
break;
}
return $control;
}
public function setValueFromRequest(AphrontRequest $request) {
$type = $this->getFieldType();
switch ($type) {
case self::TYPE_DATE:
$control = $this->renderControl();
$value = $control->readValueFromRequest($request);
break;
case self::TYPE_USER:
case self::TYPE_USERS:
$name = 'auxiliary_tokenizer_'.$this->getAuxiliaryKey();
$value = $request->getArr($name);
if ($type == self::TYPE_USER) {
$value = array_slice($value, 0, 1);
}
break;
default:
$aux_post_values = $request->getArr('auxiliary');
$value = idx($aux_post_values, $this->getAuxiliaryKey(), '');
break;
}
return $this->setValue($value);
}
public function getValueForStorage() {
switch ($this->getFieldType()) {
case self::TYPE_USER:
case self::TYPE_USERS:
return json_encode($this->getValue());
default:
- return $this->getValue();
+ return (int)$this->getValue();
}
}
public function setValueFromStorage($value) {
switch ($this->getFieldType()) {
case self::TYPE_USER:
case self::TYPE_USERS:
$value = json_decode($value, true);
if (!is_array($value)) {
$value = array();
}
break;
case self::TYPE_DATE:
$value = (int)$value;
- if ($value <= 0) {
- return $this->setDefaultValue($value);
- }
+ $this->setDefaultValue($value);
break;
default:
break;
}
return $this->setValue($value);
}
public function validate() {
switch ($this->getFieldType()) {
case self::TYPE_INT:
if ($this->getValue() && !is_numeric($this->getValue())) {
throw new ManiphestAuxiliaryFieldValidationException(
pht(
'%s must be an integer value.',
$this->getLabel()));
}
break;
case self::TYPE_BOOL:
return true;
case self::TYPE_STRING:
return true;
case self::TYPE_SELECT:
return true;
case self::TYPE_DATE:
- if ((int)$this->getValue() <= 0) {
+ if ((int)$this->getValue() <= 0 && $this->isRequired()) {
throw new ManiphestAuxiliaryFieldValidationException(
pht(
'%s must be a valid date.',
$this->getLabel()));
}
break;
case self::TYPE_USER:
case self::TYPE_USERS:
if (!is_array($this->getValue())) {
throw new ManiphestAuxiliaryFieldValidationException(
pht(
'%s is not a valid list of user PHIDs.',
$this->getLabel()));
}
break;
}
}
public function setDefaultValue($value) {
switch ($this->getFieldType()) {
case self::TYPE_DATE:
$value = strtotime($value);
if ($value <= 0) {
$value = time();
}
$this->setValue($value);
break;
case self::TYPE_USER:
case self::TYPE_USERS:
if (!is_array($value)) {
$value = array();
} else {
$value = array_values($value);
}
$this->setValue($value);
break;
default:
$this->setValue((string)$value);
break;
}
}
public function getMarkupFields() {
switch ($this->getFieldType()) {
case self::TYPE_REMARKUP:
return array('default');
}
return parent::getMarkupFields();
}
public function renderForDetailView() {
switch ($this->getFieldType()) {
case self::TYPE_BOOL:
if ($this->getValue()) {
return $this->getCheckboxValue();
} else {
return null;
}
case self::TYPE_SELECT:
return idx($this->getSelectOptions(), $this->getValue());
case self::TYPE_DATE:
return phabricator_datetime($this->getValue(), $this->getUser());
case self::TYPE_REMARKUP:
return $this->getMarkupEngine()->getOutput(
$this,
'default');
case self::TYPE_USER:
case self::TYPE_USERS:
return $this->renderHandleList($this->getValue());
case self::TYPE_HEADER:
return phutil_tag('hr');
}
return parent::renderForDetailView();
}
public function getRequiredHandlePHIDs() {
switch ($this->getFieldType()) {
case self::TYPE_USER;
case self::TYPE_USERS:
return $this->getValue();
}
return parent::getRequiredHandlePHIDs();
}
protected function renderHandleList(array $phids) {
$links = array();
foreach ($phids as $phid) {
$links[] = $this->getHandle($phid)->renderLink();
}
return phutil_implode_html(', ', $links);
}
public function renderTransactionDescription(
ManiphestTransaction $transaction,
$target) {
$label = $this->getLabel();
$old = $transaction->getOldValue();
$new = $transaction->getNewValue();
switch ($this->getFieldType()) {
case self::TYPE_BOOL:
if ($new) {
$desc = "set field '{$label}' true";
} else {
$desc = "set field '{$label}' false";
}
break;
case self::TYPE_SELECT:
$old_display = idx($this->getSelectOptions(), $old);
$new_display = idx($this->getSelectOptions(), $new);
if ($old === null) {
$desc = "set field '{$label}' to '{$new_display}'";
} else {
$desc = "changed field '{$label}' ".
"from '{$old_display}' to '{$new_display}'";
}
break;
case self::TYPE_DATE:
// NOTE: Although it should be impossible to get bad data in these
// fields normally, users can change the type of an existing field and
// leave us with uninterpretable data in old transactions.
if ((int)$new <= 0) {
- $new_display = "(invalid epoch timestamp: {$new})";
+ $new_display = "none";
} else {
$new_display = phabricator_datetime($new, $this->getUser());
}
if ($old === null) {
$desc = "set field '{$label}' to '{$new_display}'";
} else {
if ((int)$old <= 0) {
- $old_display = "(invalid epoch timestamp: {$old})";
+ $old_display = "none";
} else {
$old_display = phabricator_datetime($old, $this->getUser());
}
$desc = "changed field '{$label}' ".
"from '{$old_display}' to '{$new_display}'";
}
break;
case self::TYPE_REMARKUP:
// TODO: After we get ApplicationTransactions, straighten this out.
$desc = "updated field '{$label}'";
break;
case self::TYPE_USER:
case self::TYPE_USERS:
// TODO: As above, this is a mess that should get straightened out,
// but it will be easier after T2217.
$desc = "updated field '{$label}'";
break;
default:
if (!strlen($old)) {
if (!strlen($new)) {
return null;
}
$desc = "set field '{$label}' to '{$new}'";
} else {
$desc = "updated '{$label}' ".
"from '{$old}' to '{$new}'";
}
break;
}
return $desc;
}
public function setShouldCopyWhenCreatingSimilarTask($copy) {
$this->shouldCopyWhenCreatingSimilarTask = $copy;
return $this;
}
public function shouldCopyWhenCreatingSimilarTask() {
return $this->shouldCopyWhenCreatingSimilarTask;
}
}
diff --git a/src/applications/maniphest/controller/ManiphestTaskEditController.php b/src/applications/maniphest/controller/ManiphestTaskEditController.php
index cba05b3ec6..f578e37e0b 100644
--- a/src/applications/maniphest/controller/ManiphestTaskEditController.php
+++ b/src/applications/maniphest/controller/ManiphestTaskEditController.php
@@ -1,587 +1,594 @@
<?php
/**
* @group maniphest
*/
final class ManiphestTaskEditController extends ManiphestController {
private $id;
public function willProcessRequest(array $data) {
$this->id = idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$files = array();
$parent_task = null;
$template_id = null;
if ($this->id) {
$task = id(new ManiphestTask())->load($this->id);
if (!$task) {
return new Aphront404Response();
}
} else {
$task = new ManiphestTask();
$task->setPriority(ManiphestTaskPriority::getDefaultPriority());
$task->setAuthorPHID($user->getPHID());
// These allow task creation with defaults.
if (!$request->isFormPost()) {
$task->setTitle($request->getStr('title'));
$default_projects = $request->getStr('projects');
if ($default_projects) {
$task->setProjectPHIDs(explode(';', $default_projects));
}
$task->setDescription($request->getStr('description'));
$assign = $request->getStr('assign');
if (strlen($assign)) {
$assign_user = id(new PhabricatorUser())->loadOneWhere(
'username = %s',
$assign);
if ($assign_user) {
$task->setOwnerPHID($assign_user->getPHID());
}
}
}
$file_phids = $request->getArr('files', array());
if (!$file_phids) {
// Allow a single 'file' key instead, mostly since Mac OS X urlencodes
// square brackets in URLs when passed to 'open', so you can't 'open'
// a URL like '?files[]=xyz' and have PHP interpret it correctly.
$phid = $request->getStr('file');
if ($phid) {
$file_phids = array($phid);
}
}
if ($file_phids) {
$files = id(new PhabricatorFile())->loadAllWhere(
'phid IN (%Ls)',
$file_phids);
}
$template_id = $request->getInt('template');
// You can only have a parent task if you're creating a new task.
$parent_id = $request->getInt('parent');
if ($parent_id) {
$parent_task = id(new ManiphestTask())->load($parent_id);
if (!$template_id) {
$template_id = $parent_id;
}
}
}
$errors = array();
$e_title = true;
$extensions = ManiphestTaskExtensions::newExtensions();
$aux_fields = $extensions->loadFields($task, $user);
if ($request->isFormPost()) {
$changes = array();
$new_title = $request->getStr('title');
$new_desc = $request->getStr('description');
$new_status = $request->getStr('status');
$workflow = '';
if ($task->getID()) {
if ($new_title != $task->getTitle()) {
$changes[ManiphestTransactionType::TYPE_TITLE] = $new_title;
}
if ($new_desc != $task->getDescription()) {
$changes[ManiphestTransactionType::TYPE_DESCRIPTION] = $new_desc;
}
if ($new_status != $task->getStatus()) {
$changes[ManiphestTransactionType::TYPE_STATUS] = $new_status;
}
} else {
$task->setTitle($new_title);
$task->setDescription($new_desc);
$changes[ManiphestTransactionType::TYPE_STATUS] =
ManiphestTaskStatus::STATUS_OPEN;
$workflow = 'create';
}
$owner_tokenizer = $request->getArr('assigned_to');
$owner_phid = reset($owner_tokenizer);
if (!strlen($new_title)) {
$e_title = pht('Required');
$errors[] = pht('Title is required.');
}
- foreach ($aux_fields as $aux_field) {
+ foreach ($aux_fields as $aux_arr_key => $aux_field) {
$aux_field->setValueFromRequest($request);
+ $aux_key = $aux_field->getAuxiliaryKey();
+ $aux_old_value = $task->getAuxiliaryAttribute($aux_key);
+
+ if ((int)$aux_old_value === $aux_field->getValueForStorage()) {
+ unset($aux_fields[$aux_arr_key]);
+ continue;
+ }
if ($aux_field->isRequired() && !$aux_field->getValue()) {
$errors[] = pht('%s is required.', $aux_field->getLabel());
$aux_field->setError(pht('Required'));
}
try {
$aux_field->validate();
} catch (Exception $e) {
$errors[] = $e->getMessage();
$aux_field->setError(pht('Invalid'));
}
}
if ($errors) {
$task->setPriority($request->getInt('priority'));
$task->setOwnerPHID($owner_phid);
$task->setCCPHIDs($request->getArr('cc'));
$task->setProjectPHIDs($request->getArr('projects'));
} else {
if ($request->getInt('priority') != $task->getPriority()) {
$changes[ManiphestTransactionType::TYPE_PRIORITY] =
$request->getInt('priority');
}
if ($owner_phid != $task->getOwnerPHID()) {
$changes[ManiphestTransactionType::TYPE_OWNER] = $owner_phid;
}
if ($request->getArr('cc') != $task->getCCPHIDs()) {
$changes[ManiphestTransactionType::TYPE_CCS] = $request->getArr('cc');
}
$new_proj_arr = $request->getArr('projects');
$new_proj_arr = array_values($new_proj_arr);
sort($new_proj_arr);
$cur_proj_arr = $task->getProjectPHIDs();
$cur_proj_arr = array_values($cur_proj_arr);
sort($cur_proj_arr);
if ($new_proj_arr != $cur_proj_arr) {
$changes[ManiphestTransactionType::TYPE_PROJECTS] = $new_proj_arr;
}
if ($files) {
$file_map = mpull($files, 'getPHID');
$file_map = array_fill_keys($file_map, array());
$changes[ManiphestTransactionType::TYPE_ATTACH] = array(
PhabricatorPHIDConstants::PHID_TYPE_FILE => $file_map,
);
}
$content_source = PhabricatorContentSource::newForSource(
PhabricatorContentSource::SOURCE_WEB,
array(
'ip' => $request->getRemoteAddr(),
));
$template = new ManiphestTransaction();
$template->setAuthorPHID($user->getPHID());
$template->setContentSource($content_source);
$transactions = array();
foreach ($changes as $type => $value) {
$transaction = clone $template;
$transaction->setTransactionType($type);
$transaction->setNewValue($value);
$transactions[] = $transaction;
}
if ($aux_fields) {
foreach ($aux_fields as $aux_field) {
$transaction = clone $template;
$transaction->setTransactionType(
ManiphestTransactionType::TYPE_AUXILIARY);
$aux_key = $aux_field->getAuxiliaryKey();
$transaction->setMetadataValue('aux:key', $aux_key);
$transaction->setNewValue($aux_field->getValueForStorage());
$transactions[] = $transaction;
}
}
if ($transactions) {
$is_new = !$task->getID();
$event = new PhabricatorEvent(
PhabricatorEventType::TYPE_MANIPHEST_WILLEDITTASK,
array(
'task' => $task,
'new' => $is_new,
'transactions' => $transactions,
));
$event->setUser($user);
$event->setAphrontRequest($request);
PhutilEventEngine::dispatchEvent($event);
$task = $event->getValue('task');
$transactions = $event->getValue('transactions');
$editor = new ManiphestTransactionEditor();
$editor->setActor($user);
$editor->setAuxiliaryFields($aux_fields);
$editor->applyTransactions($task, $transactions);
$event = new PhabricatorEvent(
PhabricatorEventType::TYPE_MANIPHEST_DIDEDITTASK,
array(
'task' => $task,
'new' => $is_new,
'transactions' => $transactions,
));
$event->setUser($user);
$event->setAphrontRequest($request);
PhutilEventEngine::dispatchEvent($event);
}
if ($parent_task) {
id(new PhabricatorEdgeEditor())
->setActor($user)
->addEdge(
$parent_task->getPHID(),
PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK,
$task->getPHID())
->save();
$workflow = $parent_task->getID();
}
if ($request->isAjax()) {
return id(new AphrontAjaxResponse())->setContent(
array(
'tasks' => $this->renderSingleTask($task),
));
}
$redirect_uri = '/T'.$task->getID();
if ($workflow) {
$redirect_uri .= '?workflow='.$workflow;
}
return id(new AphrontRedirectResponse())
->setURI($redirect_uri);
}
} else {
if (!$task->getID()) {
$task->setCCPHIDs(array(
$user->getPHID(),
));
if ($template_id) {
$template_task = id(new ManiphestTask())->load($template_id);
if ($template_task) {
$task->setCCPHIDs($template_task->getCCPHIDs());
$task->setProjectPHIDs($template_task->getProjectPHIDs());
$task->setOwnerPHID($template_task->getOwnerPHID());
$task->setPriority($template_task->getPriority());
if ($aux_fields) {
$template_task->loadAndAttachAuxiliaryAttributes();
foreach ($aux_fields as $aux_field) {
if (!$aux_field->shouldCopyWhenCreatingSimilarTask()) {
continue;
}
$aux_key = $aux_field->getAuxiliaryKey();
$value = $template_task->getAuxiliaryAttribute($aux_key);
$aux_field->setValueFromStorage($value);
}
}
}
}
}
}
$phids = array_merge(
array($task->getOwnerPHID()),
$task->getCCPHIDs(),
$task->getProjectPHIDs(),
array_mergev(mpull($aux_fields, 'getRequiredHandlePHIDs')));
if ($parent_task) {
$phids[] = $parent_task->getPHID();
}
$phids = array_filter($phids);
$phids = array_unique($phids);
$handles = $this->loadViewerHandles($phids);
foreach ($aux_fields as $aux_field) {
$aux_field->setHandles($handles);
}
$tvalues = mpull($handles, 'getFullName', 'getPHID');
$error_view = null;
if ($errors) {
$error_view = new AphrontErrorView();
$error_view->setErrors($errors);
$error_view->setTitle(pht('Form Errors'));
}
$priority_map = ManiphestTaskPriority::getTaskPriorityMap();
if ($task->getOwnerPHID()) {
$assigned_value = array(
$task->getOwnerPHID() => $handles[$task->getOwnerPHID()]->getFullName(),
);
} else {
$assigned_value = array();
}
if ($task->getCCPHIDs()) {
$cc_value = array_select_keys($tvalues, $task->getCCPHIDs());
} else {
$cc_value = array();
}
if ($task->getProjectPHIDs()) {
$projects_value = array_select_keys($tvalues, $task->getProjectPHIDs());
} else {
$projects_value = array();
}
$cancel_id = nonempty($task->getID(), $template_id);
if ($cancel_id) {
$cancel_uri = '/T'.$cancel_id;
} else {
$cancel_uri = '/maniphest/';
}
if ($task->getID()) {
$button_name = pht('Save Task');
$header_name = pht('Edit Task');
} else if ($parent_task) {
$cancel_uri = '/T'.$parent_task->getID();
$button_name = pht('Create Task');
$header_name = pht('Create New Subtask');
} else {
$button_name = pht('Create Task');
$header_name = pht('Create New Task');
}
require_celerity_resource('maniphest-task-edit-css');
$project_tokenizer_id = celerity_generate_unique_node_id();
if ($request->isAjax()) {
$form = new AphrontFormLayoutView();
} else {
$form = new AphrontFormView();
$form->setFlexible(true);
$form
->setUser($user)
->addHiddenInput('template', $template_id);
}
if ($parent_task) {
$form
->appendChild(
id(new AphrontFormStaticControl())
->setLabel(pht('Parent Task'))
->setValue($handles[$parent_task->getPHID()]->getFullName()))
->addHiddenInput('parent', $parent_task->getID());
}
$form
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel(pht('Title'))
->setName('title')
->setError($e_title)
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
->setValue($task->getTitle()));
if ($task->getID()) {
// Only show this in "edit" mode, not "create" mode, since creating a
// non-open task is kind of silly and it would just clutter up the
// "create" interface.
$form
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Status'))
->setName('status')
->setValue($task->getStatus())
->setOptions(ManiphestTaskStatus::getTaskStatusMap()));
}
$form
->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Assigned To'))
->setName('assigned_to')
->setValue($assigned_value)
->setUser($user)
->setDatasource('/typeahead/common/users/')
->setLimit(1))
->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel(pht('CC'))
->setName('cc')
->setValue($cc_value)
->setUser($user)
->setDatasource('/typeahead/common/mailable/'))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Priority'))
->setName('priority')
->setOptions($priority_map)
->setValue($task->getPriority()))
->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Projects'))
->setName('projects')
->setValue($projects_value)
->setID($project_tokenizer_id)
->setCaption(
javelin_tag(
'a',
array(
'href' => '/project/create/',
'mustcapture' => true,
'sigil' => 'project-create',
),
pht('Create New Project')))
->setDatasource('/typeahead/common/projects/'));
foreach ($aux_fields as $aux_field) {
if ($aux_field->isRequired() &&
!$aux_field->getError() &&
!$aux_field->getValue()) {
$aux_field->setError(true);
}
$aux_control = $aux_field->renderControl();
$form->appendChild($aux_control);
}
require_celerity_resource('aphront-error-view-css');
Javelin::initBehavior('project-create', array(
'tokenizerID' => $project_tokenizer_id,
));
if ($files) {
$file_display = mpull($files, 'getName');
$file_display = phutil_implode_html(phutil_tag('br'), $file_display);
$form->appendChild(
id(new AphrontFormMarkupControl())
->setLabel(pht('Files'))
->setValue($file_display));
foreach ($files as $ii => $file) {
$form->addHiddenInput('files['.$ii.']', $file->getPHID());
}
}
$description_control = new PhabricatorRemarkupControl();
// "Upsell" creating tasks via email in create flows if the instance is
// configured for this awesomeness.
$email_create = PhabricatorEnv::getEnvConfig(
'metamta.maniphest.public-create-email');
if (!$task->getID() && $email_create) {
$email_hint = pht(
'You can also create tasks by sending an email to: %s',
phutil_tag('tt', array(), $email_create));
$description_control->setCaption($email_hint);
}
$description_control
->setLabel(pht('Description'))
->setName('description')
->setID('description-textarea')
->setValue($task->getDescription())
->setUser($user);
$form
->appendChild($description_control);
if ($request->isAjax()) {
$dialog = id(new AphrontDialogView())
->setUser($user)
->setWidth(AphrontDialogView::WIDTH_FULL)
->setTitle($header_name)
->appendChild(
array(
$error_view,
$form,
))
->addCancelButton($cancel_uri)
->addSubmitButton($button_name);
return id(new AphrontDialogResponse())->setDialog($dialog);
}
$form
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton($cancel_uri)
->setValue($button_name));
$inst1 = pht('Description Preview');
$inst2 = pht('Loading preview...');
$description_preview_panel = hsprintf(
'<div class="aphront-panel-preview aphront-panel-preview-full">
<div class="maniphest-description-preview-header">
%s
</div>
<div id="description-preview">
<div class="aphront-panel-preview-loading-text">
%s
</div>
</div>
</div>',
$inst1,
$inst2);
Javelin::initBehavior(
'maniphest-description-preview',
array(
'preview' => 'description-preview',
'textarea' => 'description-textarea',
'uri' => '/maniphest/task/descriptionpreview/',
));
if ($task->getID()) {
$page_objects = array( $task->getPHID() );
} else {
$page_objects = array();
}
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($header_name)
->setHref($this->getApplicationURI('/task/create/')))
->addAction(
id(new PHUIListItemView())
->setHref($this->getApplicationURI('/task/create/'))
->setName(pht('Create Task'))
->setIcon('create'));
return $this->buildApplicationPage(
array(
$crumbs,
$error_view,
$form,
$description_preview_panel,
),
array(
'title' => $header_name,
'pageObjects' => $page_objects,
'device' => true,
));
}
}
diff --git a/webroot/rsrc/css/phui/phui-form.css b/webroot/rsrc/css/phui/phui-form.css
index 09139df1ad..92bdacc40e 100644
--- a/webroot/rsrc/css/phui/phui-form.css
+++ b/webroot/rsrc/css/phui/phui-form.css
@@ -1,134 +1,135 @@
/**
* @provides phui-form-css
*/
select,
textarea,
input[type="text"],
input[type="password"],
input[type="datetime"],
input[type="datetime-local"],
input[type="date"],
input[type="month"],
input[type="time"],
input[type="week"],
input[type="number"],
input[type="email"],
input[type="url"],
input[type="search"],
input[type="tel"],
input[type="color"],
div.jx-tokenizer-container {
display: inline-block;
height: 28px;
line-height: 18px;
color: #333;
vertical-align: middle;
font: 13px 'Helvetica Neue', Arial, sans-serif;
}
textarea,
input[type="text"],
input[type="password"],
input[type="datetime"],
input[type="datetime-local"],
input[type="date"],
input[type="month"],
input[type="time"],
input[type="week"],
input[type="number"],
input[type="email"],
input[type="url"],
input[type="search"],
input[type="tel"],
input[type="color"],
div.jx-tokenizer-container {
padding: 4px 6px;
background-color: #ffffff;
border: 1px solid #96A6C5;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-webkit-transition: border linear .05s, box-shadow linear .05s;
-moz-transition: border linear .05s, box-shadow linear .05s;
-o-transition: border linear .05s, box-shadow linear .05s;
transition: border linear .05s, box-shadow linear .05s;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
/* iOS Safari */
-webkit-appearance: none;
border-radius: 0;
}
textarea:focus,
input[type="text"]:focus,
input[type="password"]:focus,
input[type="datetime"]:focus,
input[type="datetime-local"]:focus,
input[type="date"]:focus,
input[type="month"]:focus,
input[type="time"]:focus,
input[type="week"]:focus,
input[type="number"]:focus,
input[type="email"]:focus,
input[type="url"]:focus,
input[type="search"]:focus,
input[type="tel"]:focus,
input[type="color"]:focus,
div.jx-tokenizer-container-focused {
border-color: rgba(82, 168, 236, 0.8);
outline: 0;
/* IE6-9 */
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
}
input[type="radio"],
input[type="checkbox"] {
margin: 4px 0 0;
margin-top: 1px \9;
/* IE8-9 */
line-height: normal;
}
select {
height: 24px;
line-height: 24px;
border: 1px solid #a1a5a9;
background-color: #ffffff;
}
select[multiple],
select[size] {
height: auto;
}
select:focus,
input[type="file"]:focus,
input[type="radio"]:focus,
input[type="checkbox"]:focus {
outline: thin dotted #333;
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
}
input:-moz-placeholder,
textarea:-moz-placeholder {
color: #999999;
}
input:-ms-input-placeholder,
textarea:-ms-input-placeholder {
color: #999999;
}
input::-webkit-input-placeholder,
textarea::-webkit-input-placeholder {
color: #999999;
}
-select[disabled="disabled"] {
+select[disabled="disabled"],
+input[disabled="disabled"] {
opacity: 0.5;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 18:02 (1 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1127214
Default Alt Text
(34 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment