Page MenuHomePhorge

No OneTemporary

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

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)

Event Timeline