diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index aee2c0ca26..4639052473 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -45,7 +45,7 @@ celerity_register_resource_map(array( ), 'aphront-form-view-css' => array( - 'uri' => '/res/8aaef437/rsrc/css/aphront/form-view.css', + 'uri' => '/res/472d41b4/rsrc/css/aphront/form-view.css', 'type' => 'css', 'requires' => array( @@ -215,6 +215,24 @@ celerity_register_resource_map(array( ), 'disk' => '/rsrc/css/application/directory/phabricator-directory.css', ), + 'herald-test-css' => + array( + 'uri' => '/res/28269358/rsrc/css/application/herald/herald-test.css', + 'type' => 'css', + 'requires' => + array( + ), + 'disk' => '/rsrc/css/application/herald/herald-test.css', + ), + 'herald-css' => + array( + 'uri' => '/res/211a4b1b/rsrc/css/application/herald/herald.css', + 'type' => 'css', + 'requires' => + array( + ), + 'disk' => '/rsrc/css/application/herald/herald.css', + ), 'mainphest-task-detail-css' => array( 'uri' => '/res/e5f3beca/rsrc/css/application/maniphest/task-detail.css', @@ -524,7 +542,7 @@ celerity_register_resource_map(array( ), array ( 'packages' => array ( - '848f4c9f' => + 'abe939ec' => array ( 'name' => 'core.pkg.css', 'symbols' => @@ -544,7 +562,7 @@ celerity_register_resource_map(array( 12 => 'phabricator-remarkup-css', 13 => 'syntax-highlighting-css', ), - 'uri' => '/res/pkg/848f4c9f/core.pkg.css', + 'uri' => '/res/pkg/abe939ec/core.pkg.css', 'type' => 'css', ), '76f3c1f8' => @@ -591,20 +609,20 @@ celerity_register_resource_map(array( ), 'reverse' => array ( - 'phabricator-core-css' => '848f4c9f', - 'phabricator-core-buttons-css' => '848f4c9f', - 'phabricator-standard-page-view' => '848f4c9f', - 'aphront-dialog-view-css' => '848f4c9f', - 'aphront-form-view-css' => '848f4c9f', - 'aphront-panel-view-css' => '848f4c9f', - 'aphront-side-nav-view-css' => '848f4c9f', - 'aphront-table-view-css' => '848f4c9f', - 'aphront-crumbs-view-css' => '848f4c9f', - 'aphront-tokenizer-control-css' => '848f4c9f', - 'aphront-typeahead-control-css' => '848f4c9f', - 'phabricator-directory-css' => '848f4c9f', - 'phabricator-remarkup-css' => '848f4c9f', - 'syntax-highlighting-css' => '848f4c9f', + 'phabricator-core-css' => 'abe939ec', + 'phabricator-core-buttons-css' => 'abe939ec', + 'phabricator-standard-page-view' => 'abe939ec', + 'aphront-dialog-view-css' => 'abe939ec', + 'aphront-form-view-css' => 'abe939ec', + 'aphront-panel-view-css' => 'abe939ec', + 'aphront-side-nav-view-css' => 'abe939ec', + 'aphront-table-view-css' => 'abe939ec', + 'aphront-crumbs-view-css' => 'abe939ec', + 'aphront-tokenizer-control-css' => 'abe939ec', + 'aphront-typeahead-control-css' => 'abe939ec', + 'phabricator-directory-css' => 'abe939ec', + 'phabricator-remarkup-css' => 'abe939ec', + 'syntax-highlighting-css' => 'abe939ec', 'differential-core-view-css' => '76f3c1f8', 'differential-changeset-view-css' => '76f3c1f8', 'differential-revision-detail-css' => '76f3c1f8', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 466921edfb..e9e893c140 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -188,6 +188,7 @@ phutil_register_library_map(array( 'HeraldContentTypeConfig' => 'applications/herald/config/contenttype', 'HeraldController' => 'applications/herald/controller/base', 'HeraldDAO' => 'applications/herald/storage/base', + 'HeraldDeleteController' => 'applications/herald/controller/delete', 'HeraldEffect' => 'applications/herald/engine/effect', 'HeraldEngine' => 'applications/herald/engine/engine', 'HeraldFieldConfig' => 'applications/herald/config/field', @@ -536,6 +537,7 @@ phutil_register_library_map(array( 'HeraldCondition' => 'HeraldDAO', 'HeraldController' => 'PhabricatorController', 'HeraldDAO' => 'PhabricatorLiskDAO', + 'HeraldDeleteController' => 'HeraldController', 'HeraldHomeController' => 'HeraldController', 'HeraldNewController' => 'HeraldController', 'HeraldRule' => 'HeraldDAO', diff --git a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php index f80844fee8..8aa5b33a06 100644 --- a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php +++ b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php @@ -222,6 +222,7 @@ class AphrontDefaultApplicationConfiguration 'view/(?P[^/]+)/$' => 'HeraldHomeController', 'new/(?:(?P[^/]+)/)?$' => 'HeraldNewController', 'rule/(?:(?\d+)/)?$' => 'HeraldRuleController', + 'delete/(?P\d+)/$' => 'HeraldDeleteController', ), ); diff --git a/src/applications/herald/controller/delete/HeraldDeleteController.php b/src/applications/herald/controller/delete/HeraldDeleteController.php new file mode 100644 index 0000000000..a4cbc4f131 --- /dev/null +++ b/src/applications/herald/controller/delete/HeraldDeleteController.php @@ -0,0 +1,64 @@ +id = $data['id']; + } + + public function processRequest() { + + $rule = id(new HeraldRule())->load($this->id); + if (!$rule) { + return new Aphront404Response(); + } + + $request = $this->getRequest(); + $user = $request->getUser(); + + if ($user->getPHID() != $rule->getAuthorPHID()) { + return new Aphront400Response(); + } + + if ($request->isFormPost()) { + $rule->delete(); + if ($request->isAjax()) { + return new AphrontRedirectResponse(); + } else { + return id(new AphrontRedirectResponse())->setURI('/herald/'); + } + } + + $dialog = new AphrontDialogView(); + $dialog->setUser($request->getUser()); + $dialog->setTitle('Really delete this rule?'); + $dialog->appendChild( + "Are you sure you want to delete the rule ". + "'".phutil_escape_html($rule->getName())."'?"); + $dialog->addSubmitButton('Delete'); + $dialog->addCancelButton('/herald/'); + $dialog->setSubmitURI($request->getPath()); + + return id(new AphrontDialogResponse())->setDialog($dialog); + + } + +} diff --git a/src/applications/herald/controller/delete/__init__.php b/src/applications/herald/controller/delete/__init__.php new file mode 100644 index 0000000000..739c92f27d --- /dev/null +++ b/src/applications/herald/controller/delete/__init__.php @@ -0,0 +1,21 @@ +view, $user->getPHID()); - $handles = array(); $need_phids = mpull($rules, 'getAuthorPHID'); + $handles = id(new PhabricatorObjectHandleData($need_phids)) + ->loadHandles(); -/* - $data = new ToolsHandleData($need_fbids, $handles); - $data->needNames(); - $data->needAlternateNames(); - prep($data); -*/ $type = 'differential'; $rows = array(); foreach ($rules as $rule) { + $owner = $handles[$rule->getAuthorPHID()]->renderLink(); + + $name = phutil_render_tag( + 'a', + array( + 'href' => '/herald/rule/'.$rule->getID().'/', + ), + phutil_escape_html($rule->getName())); - $owner = 'owner'; -/* getOwnerID()]->getURI()}> - {$handles[$rule->getOwnerID()]->getName()} - ; -*/ - $name = 'name'; -/* getID()."/"}> - {$rule->getName()} - ; -*/ $delete = 'delete'; + $delete = javelin_render_tag( + 'a', + array( + 'href' => '/herald/delete/'.$rule->getID().'/', + 'sigil' => 'workflow', + 'class' => 'button small grey', + ), + 'Delete'); -/* getID()."/"} workflow={true}> - Delete - ; -*/ $rows[] = array( $map[$rule->getContentType()], - $owner->toString(), - $name->toString(), - $delete->toString(), + $owner, + $name, + $delete, ); } @@ -89,13 +86,13 @@ class HeraldHomeController extends HeraldController { 'Type', 'Owner', 'Rule Name', - 'Delete', + '', )); $table->setColumnClasses( array( '', '', - 'wide wrap', + 'wide wrap pri', 'action' )); diff --git a/src/applications/herald/controller/home/__init__.php b/src/applications/herald/controller/home/__init__.php index da89fa3163..f72d87f3cf 100644 --- a/src/applications/herald/controller/home/__init__.php +++ b/src/applications/herald/controller/home/__init__.php @@ -9,6 +9,8 @@ phutil_require_module('phabricator', 'applications/herald/config/contenttype'); phutil_require_module('phabricator', 'applications/herald/controller/base'); phutil_require_module('phabricator', 'applications/herald/storage/rule'); +phutil_require_module('phabricator', 'applications/phid/handle/data'); +phutil_require_module('phabricator', 'infrastructure/javelin/markup'); phutil_require_module('phabricator', 'view/control/table'); phutil_require_module('phabricator', 'view/layout/panel'); phutil_require_module('phabricator', 'view/layout/sidenav'); diff --git a/src/applications/herald/controller/rule/HeraldRuleController.php b/src/applications/herald/controller/rule/HeraldRuleController.php index 1de1429135..b53d91deb6 100644 --- a/src/applications/herald/controller/rule/HeraldRuleController.php +++ b/src/applications/herald/controller/rule/HeraldRuleController.php @@ -68,16 +68,14 @@ class HeraldRuleController extends HeraldController { $rule->attachConditions($rule_conditions); $rule->attachActions($rule_actions); - $arr = "\xC2\xAB"; $e_name = true; $errors = array(); if ($request->isFormPost() && $request->getStr('save')) { - $rule->setName($request->getStr('name')); $rule->setMustMatchAll(($request->getStr('must_match') == 'all')); if (!strlen($rule->getName())) { - $e_name = "{$arr} Required"; + $e_name = "Required"; $errors[] = "Rule must have a name."; } @@ -92,7 +90,7 @@ class HeraldRuleController extends HeraldController { foreach ($data['conditions'] as $condition) { $obj = new HeraldCondition(); $obj->setFieldName($condition[0]); - $obj->setCondition($condition[1]); + $obj->setFieldCondition($condition[1]); if (is_array($condition[2])) { $obj->setValue(array_keys($condition[2])); @@ -100,7 +98,7 @@ class HeraldRuleController extends HeraldController { $obj->setValue($condition[2]); } - $cond_type = $obj->getCondition(); + $cond_type = $obj->getFieldCondition(); if ($cond_type == HeraldConditionConfig::CONDITION_REGEXP) { if (@preg_match($obj->getValue(), '') === false) { @@ -170,18 +168,19 @@ class HeraldRuleController extends HeraldController { if (!$errors) { try { - $rule->openTransaction(); +// TODO +// $rule->openTransaction(); $rule->save(); $rule->saveConditions($conditions); $rule->saveActions($actions); - $rule->saveTransaction(); +// $rule->saveTransaction(); $uri = '/herald/view/'.$rule->getContentType().'/'; return id(new AphrontRedirectResponse()) ->setURI($uri); - } catch (QueryDuplicateKeyException $ex) { - $e_name = "{$arr} Not Unique"; + } catch (AphrontQueryDuplicateKeyException $ex) { + $e_name = "Not Unique"; $errors[] = "Rule name is not unique. Choose a unique name."; } } @@ -213,13 +212,13 @@ class HeraldRuleController extends HeraldController { ->loadHandles(); if ($errors) { - $errors = '!!';//; + $error_view = new AphrontErrorView(); + $error_view->setTitle('Form Errors'); + $error_view->setErrors($errors); + } else { + $error_view = null; } - -// require_static('herald-css'); - - $options = array( 'all' => 'all of', 'any' => 'any of', @@ -233,6 +232,7 @@ class HeraldRuleController extends HeraldController { 'option', array( 'selected' => ($selected == $key) ? 'selected' : null, + 'value' => $key, ), phutil_escape_html($option)); } @@ -247,17 +247,28 @@ class HeraldRuleController extends HeraldController { $action = '/herald/rule/'.$rule->getID().'/'; } + require_celerity_resource('herald-css'); + $type_name = $content_type_map[$rule->getContentType()]; $form = id(new AphrontFormView()) ->setUser($user) ->setID('herald-rule-edit-form') ->addHiddenInput('type', $rule->getContentType()) - ->addHiddenInput('save', true) - ->addHiddenInput('rule', '') + ->addHiddenInput('save', 1) + ->appendChild( + // Build this explicitly so we can add a sigil to it. + javelin_render_tag( + 'input', + array( + 'type' => 'hidden', + 'name' => 'rule', + 'sigil' => 'rule', + ))) ->appendChild( id(new AphrontFormTextControl()) ->setLabel('Rule Name') + ->setName('name') ->setError($e_name) ->setValue($rule->getName())) ->appendChild( @@ -270,27 +281,32 @@ class HeraldRuleController extends HeraldController { "This rule triggers for {$type_name}.")) ->appendChild( '

Conditions

'. - '
'. - javelin_render_tag( - 'a', - array( - 'href' => '#', - 'class' => 'button green', - 'sigil' => 'create-condition', - 'mustcapture' => true, - ), - 'Create New Condition'). + '
'. + '
'. + javelin_render_tag( + 'a', + array( + 'href' => '#', + 'class' => 'button green', + 'sigil' => 'create-condition', + 'mustcapture' => true, + ), + 'Create New Condition'). + '
'. '

When '.$must_match.' these conditions are met:

'. + '
'. javelin_render_tag( 'table', array( 'sigil' => 'rule-conditions', + 'class' => 'herald-condition-table', ), ''). '
') ->appendChild( '

Action

'. - '
'. + '
'. + '
'. javelin_render_tag( 'a', array( @@ -300,11 +316,14 @@ class HeraldRuleController extends HeraldController { 'mustcapture' => true, ), 'Create New Action'). + '
'. '

Take these actions:

'. + '
'. javelin_render_tag( 'table', array( 'sigil' => 'rule-actions', + 'class' => 'herald-action-table', ), ''). '
') @@ -312,86 +331,11 @@ class HeraldRuleController extends HeraldController { id(new AphrontFormSubmitControl()) ->setValue('Save Rule') ->addCancelButton('/herald/view/'.$rule->getContentType().'/')); -/* - $form = -
- - - - getStr('type')} /> - - {$errors} - -

Edit Rule

- - - - getName()} /> - - - - {$handles[$rule->getAuthorPHID()]->getName()} - - - - This rule triggers for - {$content_type_map[$rule->getContentType()]}. - - - - -

Conditions

- - -
- - - When {$must_match} these conditions are met: - -
-
- - - - -

Actions

- -
- - Take these actions: -
-
-
- - -
- - - Cancel - -
- - - ; - -*/ $serial_conditions = array( array('default', 'default', ''), ); + if ($rule->getConditions()) { $serial_conditions = array(); foreach ($rule->getConditions() as $condition) { @@ -400,14 +344,14 @@ class HeraldRuleController extends HeraldController { if (is_array($value)) { $value_map = array(); foreach ($value as $k => $fbid) { - $value_map[$fbid] = $handles[$fbid]->getExtendedDisplayName(); + $value_map[$fbid] = $handles[$fbid]->getName(); } $value = $value_map; } $serial_conditions[] = array( $condition->getFieldName(), - $condition->getCondition(), + $condition->getFieldCondition(), $value, ); } @@ -422,7 +366,7 @@ class HeraldRuleController extends HeraldController { $target_map = array(); foreach ((array)$action->getTarget() as $fbid) { - $target_map[$fbid] = $handles[$fbid]->getExtendedDisplayName(); + $target_map[$fbid] = $handles[$fbid]->getName(); } $serial_actions[] = array( @@ -484,7 +428,10 @@ class HeraldRuleController extends HeraldController { $panel->appendChild($form); return $this->buildStandardPageResponse( - $panel, + array( + $error_view, + $panel, + ), array( 'title' => 'Edit Rule', )); diff --git a/src/applications/herald/controller/rule/__init__.php b/src/applications/herald/controller/rule/__init__.php index 568bc59144..2ab2443e61 100644 --- a/src/applications/herald/controller/rule/__init__.php +++ b/src/applications/herald/controller/rule/__init__.php @@ -18,10 +18,12 @@ phutil_require_module('phabricator', 'applications/herald/storage/action'); phutil_require_module('phabricator', 'applications/herald/storage/condition'); phutil_require_module('phabricator', 'applications/herald/storage/rule'); 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', 'view/control/tokenizer'); phutil_require_module('phabricator', 'view/form/base'); phutil_require_module('phabricator', 'view/form/control/submit'); +phutil_require_module('phabricator', 'view/form/error'); phutil_require_module('phabricator', 'view/layout/panel'); phutil_require_module('phutil', 'markup'); diff --git a/src/applications/herald/storage/action/HeraldAction.php b/src/applications/herald/storage/action/HeraldAction.php index b667095181..ed63a2216c 100644 --- a/src/applications/herald/storage/action/HeraldAction.php +++ b/src/applications/herald/storage/action/HeraldAction.php @@ -27,7 +27,8 @@ class HeraldAction extends HeraldDAO { return array( self::CONFIG_SERIALIZATION => array( 'target' => self::SERIALIZATION_JSON, - ) + ), + self::CONFIG_TIMESTAMPS => false, ) + parent::getConfiguration(); } diff --git a/src/applications/herald/storage/condition/HeraldCondition.php b/src/applications/herald/storage/condition/HeraldCondition.php index ac819c769e..3a60d29124 100644 --- a/src/applications/herald/storage/condition/HeraldCondition.php +++ b/src/applications/herald/storage/condition/HeraldCondition.php @@ -21,14 +21,15 @@ class HeraldCondition extends HeraldDAO { protected $ruleID; protected $fieldName; - protected $condition; + protected $fieldCondition; protected $value; protected function getConfiguration() { return array( self::CONFIG_SERIALIZATION => array( 'value' => self::SERIALIZATION_JSON, - ) + ), + self::CONFIG_TIMESTAMPS => false, ) + parent::getConfiguration(); } diff --git a/src/applications/herald/storage/rule/HeraldRule.php b/src/applications/herald/storage/rule/HeraldRule.php index 24dabbbe8f..f4a5849fdf 100644 --- a/src/applications/herald/storage/rule/HeraldRule.php +++ b/src/applications/herald/storage/rule/HeraldRule.php @@ -112,7 +112,8 @@ class HeraldRule extends HeraldDAO { // TODO: // $this->openTransaction(); - $this->getLink('w')->query( + queryfx( + $this->establishConnection('w'), 'DELETE FROM %T WHERE ruleID = %d', $table_name, $this->getID()); @@ -126,11 +127,13 @@ class HeraldRule extends HeraldDAO { // TODO: // $this->openTransaction(); - $this->getLink('w')->query( + queryfx( + $this->establishConnection('w'), 'DELETE FROM %T WHERE ruleID = %d', id(new HeraldCondition())->getTableName(), $this->getID()); - $this->getLink('w')->query( + queryfx( + $this->establishConnection('w'), 'DELETE FROM %T WHERE ruleID = %d', id(new HeraldAction())->getTableName(), $this->getID()); diff --git a/src/applications/herald/storage/rule/__init__.php b/src/applications/herald/storage/rule/__init__.php index d40a9ab37c..99772266f3 100644 --- a/src/applications/herald/storage/rule/__init__.php +++ b/src/applications/herald/storage/rule/__init__.php @@ -9,6 +9,7 @@ phutil_require_module('phabricator', 'applications/herald/storage/action'); phutil_require_module('phabricator', 'applications/herald/storage/base'); phutil_require_module('phabricator', 'applications/herald/storage/condition'); +phutil_require_module('phabricator', 'storage/queryfx'); phutil_require_module('phutil', 'utils'); diff --git a/webroot/rsrc/css/aphront/form-view.css b/webroot/rsrc/css/aphront/form-view.css index c094df9477..ce6a52a4c9 100644 --- a/webroot/rsrc/css/aphront/form-view.css +++ b/webroot/rsrc/css/aphront/form-view.css @@ -103,4 +103,11 @@ table.aphront-form-control-checkbox-layout th { background: #bbbbbb; height: 1px; position: relative; -} \ No newline at end of file +} + +.aphront-form-inset { + margin: 0 0 1em; + padding: .75em; + background: #f3f3f3; + border: 1px solid #afafaf; +} diff --git a/webroot/rsrc/css/application/herald/herald-test.css b/webroot/rsrc/css/application/herald/herald-test.css new file mode 100644 index 0000000000..83292bf995 --- /dev/null +++ b/webroot/rsrc/css/application/herald/herald-test.css @@ -0,0 +1,100 @@ +/** + * @provides herald-test-css + */ + +ul.herald-explain-list { + font-size: 11px; + font-family: "Verdana"; +} + +div.herald-condition-note { + clear: both; + margin: .5em 0em .53em 86px; + padding: .5em 1em; + background: #FFFF00; + font-weight: bold; +} + +ul.herald-explain-list .herald-outcome { + margin-right: 6px; + width: 50px; + text-align: center; + position: relative; + float: left; + font-weight: bold; + padding: 1px 2px; +} + +ul.herald-explain-list .condition-fail, +ul.herald-explain-list .rule-fail { + color: #aa0000; +} + +ul.herald-explain-list .condition-pass, +ul.herald-explain-list .rule-pass { + color: #00aa00; +} + + + +ul.herald-explain-list li.herald-rule-pass, +ul.herald-explain-list li.herald-rule-fail { + margin: 0 0 0.75em; +} + +ul.herald-explain-list li.herald-rule-fail { + border: 1px solid #aa0000; +} + +ul.herald-explain-list li.herald-rule-pass { + border: 1px solid #00aa00; +} + +ul.herald-explain-list div.rule-name { + border-bottom: 1px solid #cccccc; + font-size: 12px; + padding: .5em .75em; +} + +ul.herald-explain-list li.herald-rule-fail, +ul.herald-explain-list li.herald-rule-pass { + background: #ffffff; +} + +ul.herald-explain-list ul { + margin: .5em; +} + +ul.herald-explain-list ul li { + padding: 2px 0; +} + +.outcome-failure, +.outcome-success { + font-weight: bold; +} + +.outcome-failure { + color: #990000; +} + +.outcome-success { + color: #009900; +} + + +.action-header { + font-weight: bold; + padding-top: 1em; + border-bottom: 1px solid #dddddd; +} + +textarea.herald-field-value-transcript { + width: 100%; + height: 10em; +} + + +.condition-test-value { + color: #666666; +} diff --git a/webroot/rsrc/css/application/herald/herald.css b/webroot/rsrc/css/application/herald/herald.css new file mode 100644 index 0000000000..f8867e9934 --- /dev/null +++ b/webroot/rsrc/css/application/herald/herald.css @@ -0,0 +1,31 @@ +/** + * @provides herald-css + */ + +.herald-action-table, +.herald-condition-table { + margin-top: 8px; +} + +.herald-condition-table select { + width: 250px; +} + +.herald-action-table td, +.herald-condition-table td { + padding: 2px 4px; + vertical-align: middle; +} + +.herald-condition-table td.value { + width: 100%; +} + +.herald-action-table td input, +.herald-condition-table td input { + width: 460px; +} + +.herald-action-table td.target { + width: 100%; +}