From b8a03bc145b124d559e613868323eccf5c9ebbac Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Sat, 18 May 2024 10:06:53 +0200 Subject: [PATCH] Workboard Trigger Rule: allow to Add/Remove Subscribers Summary: This is a natural expansion of the Workboard Trigger system to support actions about Subscribers. Context: even before this change - Workboard users were already able to move Tasks to Columns with nice automatisms. For instance, you can already: - Play a nice Sound - Change Task Priority - Change Task Status - Add or Remove a Task Owner - Add or Remove a Task Project Tag With this change, you can also: - Add or Remove Task Subscribers If you need inspiration, this feature is useful for adding more eyes on a given work area; lighten the notifications of certain people after certain workflows have already been done, to increase happiness and mitigate Burnout. If your goal is to oppress yourself or your coworkers - of course you can also use this feature to increase the Burnout of yourself or your coworkers, adding random people as Subscriber. Note: every trigger action can be confusing in general, but it is the fault of Triggers in general and not related to this specific feature - that is totally loveable, just like you. Closes T15162 Test Plan: - Workboard > Column > Create Trigger - Add Action > Add Subscriber > (your best friend who hates NodeJS) - Add Action > Remove Subscriber > (your antagonist who hates PHP) - Move some Tasks there and here, and note that Add/Remove works Reviewers: O1 Blessed Committers, Cigaryno, aklapper Reviewed By: O1 Blessed Committers, Cigaryno, aklapper Subscribers: aklapper, speck, tobiaswiese, Matthew, Cigaryno Tags: #workboard Maniphest Tasks: T15162 Differential Revision: https://we.phorge.it/D25080 --- src/__phutil_library_map__.php | 4 + ...icatorProjectTriggerAddSubscribersRule.php | 127 ++++++++++++++++++ ...torProjectTriggerRemoveSubscribersRule.php | 127 ++++++++++++++++++ 3 files changed, 258 insertions(+) create mode 100644 src/applications/project/trigger/PhabricatorProjectTriggerAddSubscribersRule.php create mode 100644 src/applications/project/trigger/PhabricatorProjectTriggerRemoveSubscribersRule.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index b21f29d1b4..02e4c7f2b3 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4491,6 +4491,7 @@ phutil_register_library_map(array( 'PhabricatorProjectTransactionType' => 'applications/project/xaction/PhabricatorProjectTransactionType.php', 'PhabricatorProjectTrigger' => 'applications/project/storage/PhabricatorProjectTrigger.php', 'PhabricatorProjectTriggerAddProjectsRule' => 'applications/project/trigger/PhabricatorProjectTriggerAddProjectsRule.php', + 'PhabricatorProjectTriggerAddSubscribersRule' => 'applications/project/trigger/PhabricatorProjectTriggerAddSubscribersRule.php', 'PhabricatorProjectTriggerController' => 'applications/project/controller/trigger/PhabricatorProjectTriggerController.php', 'PhabricatorProjectTriggerCorruptionException' => 'applications/project/exception/PhabricatorProjectTriggerCorruptionException.php', 'PhabricatorProjectTriggerEditController' => 'applications/project/controller/trigger/PhabricatorProjectTriggerEditController.php', @@ -4505,6 +4506,7 @@ phutil_register_library_map(array( 'PhabricatorProjectTriggerPlaySoundRule' => 'applications/project/trigger/PhabricatorProjectTriggerPlaySoundRule.php', 'PhabricatorProjectTriggerQuery' => 'applications/project/query/PhabricatorProjectTriggerQuery.php', 'PhabricatorProjectTriggerRemoveProjectsRule' => 'applications/project/trigger/PhabricatorProjectTriggerRemoveProjectsRule.php', + 'PhabricatorProjectTriggerRemoveSubscribersRule' => 'applications/project/trigger/PhabricatorProjectTriggerRemoveSubscribersRule.php', 'PhabricatorProjectTriggerRule' => 'applications/project/trigger/PhabricatorProjectTriggerRule.php', 'PhabricatorProjectTriggerRuleRecord' => 'applications/project/trigger/PhabricatorProjectTriggerRuleRecord.php', 'PhabricatorProjectTriggerRulesetTransaction' => 'applications/project/xaction/trigger/PhabricatorProjectTriggerRulesetTransaction.php', @@ -11129,6 +11131,7 @@ phutil_register_library_map(array( 'PhabricatorDestructibleInterface', ), 'PhabricatorProjectTriggerAddProjectsRule' => 'PhabricatorProjectTriggerRule', + 'PhabricatorProjectTriggerAddSubscribersRule' => 'PhabricatorProjectTriggerRule', 'PhabricatorProjectTriggerController' => 'PhabricatorProjectController', 'PhabricatorProjectTriggerCorruptionException' => 'Exception', 'PhabricatorProjectTriggerEditController' => 'PhabricatorProjectTriggerController', @@ -11143,6 +11146,7 @@ phutil_register_library_map(array( 'PhabricatorProjectTriggerPlaySoundRule' => 'PhabricatorProjectTriggerRule', 'PhabricatorProjectTriggerQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorProjectTriggerRemoveProjectsRule' => 'PhabricatorProjectTriggerRule', + 'PhabricatorProjectTriggerRemoveSubscribersRule' => 'PhabricatorProjectTriggerRule', 'PhabricatorProjectTriggerRule' => 'Phobject', 'PhabricatorProjectTriggerRuleRecord' => 'Phobject', 'PhabricatorProjectTriggerRulesetTransaction' => 'PhabricatorProjectTriggerTransactionType', diff --git a/src/applications/project/trigger/PhabricatorProjectTriggerAddSubscribersRule.php b/src/applications/project/trigger/PhabricatorProjectTriggerAddSubscribersRule.php new file mode 100644 index 0000000000..28b0c614fe --- /dev/null +++ b/src/applications/project/trigger/PhabricatorProjectTriggerAddSubscribersRule.php @@ -0,0 +1,127 @@ +getDatasource()->getWireTokens($this->getValue()); + } + + protected function assertValidRuleRecordFormat($value) { + if (!is_array($value)) { + throw new Exception( + pht( + 'Add subscribers rule value should be a list, but is not '. + '(value is "%s").', + phutil_describe_type($value))); + } + } + + protected function assertValidRuleRecordValue($value) { + if (!$value) { + throw new Exception( + pht( + 'You must select at least one user or project tag to add.')); + } + } + + protected function newDropTransactions($object, $value) { + $subscriber_edge_type = PhabricatorObjectHasSubscriberEdgeType::EDGECONST; + + $xaction = $object->getApplicationTransactionTemplate() + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue('edge:type', $subscriber_edge_type) + ->setNewValue( + array( + '+' => array_fuse($value), + )); + + return array($xaction); + } + + protected function newDropEffects($value) { + return array( + $this->newEffect() + ->setIcon('fa-briefcase') + ->setContent($this->getRuleViewDescription($value)), + ); + } + + protected function getDefaultValue() { + return null; + } + + protected function getPHUIXControlType() { + return 'tokenizer'; + } + + private function getDatasource() { + $datasource = new PhabricatorProjectOrUserDatasource(); + + if ($this->getViewer()) { + $datasource->setViewer($this->getViewer()); + } + + return $datasource; + } + + protected function getPHUIXControlSpecification() { + $template = id(new AphrontTokenizerTemplateView()) + ->setViewer($this->getViewer()); + + $template_markup = $template->render(); + $datasource = $this->getDatasource(); + + return array( + 'markup' => (string)hsprintf('%s', $template_markup), + 'config' => array( + 'src' => $datasource->getDatasourceURI(), + 'browseURI' => $datasource->getBrowseURI(), + 'placeholder' => $datasource->getPlaceholderText(), + 'limit' => $datasource->getLimit(), + ), + 'value' => null, + ); + } + + public function getRuleViewLabel() { + return pht('Add subscribers'); + } + + public function getRuleViewDescription($value) { + return pht( + 'Add subscribers: %s.', + phutil_tag( + 'strong', + array(), + $this->getViewer() + ->renderHandleList($value) + ->setAsInline(true) + ->render())); + } + + public function getRuleViewIcon($value) { + return id(new PHUIIconView()) + ->setIcon('fa-users', 'green'); + } + + +} diff --git a/src/applications/project/trigger/PhabricatorProjectTriggerRemoveSubscribersRule.php b/src/applications/project/trigger/PhabricatorProjectTriggerRemoveSubscribersRule.php new file mode 100644 index 0000000000..2cd3fadfee --- /dev/null +++ b/src/applications/project/trigger/PhabricatorProjectTriggerRemoveSubscribersRule.php @@ -0,0 +1,127 @@ +getDatasource()->getWireTokens($this->getValue()); + } + + protected function assertValidRuleRecordFormat($value) { + if (!is_array($value)) { + throw new Exception( + pht( + 'Remove subscribers rule value should be a list, but is not '. + '(value is "%s").', + phutil_describe_type($value))); + } + } + + protected function assertValidRuleRecordValue($value) { + if (!$value) { + throw new Exception( + pht( + 'You must select at least one user or project tag to remove.')); + } + } + + protected function newDropTransactions($object, $value) { + $subscriber_edge_type = PhabricatorObjectHasSubscriberEdgeType::EDGECONST; + + $xaction = $object->getApplicationTransactionTemplate() + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue('edge:type', $subscriber_edge_type) + ->setNewValue( + array( + '-' => array_fuse($value), + )); + + return array($xaction); + } + + protected function newDropEffects($value) { + return array( + $this->newEffect() + ->setIcon('fa-briefcase') + ->setContent($this->getRuleViewDescription($value)), + ); + } + + protected function getDefaultValue() { + return null; + } + + protected function getPHUIXControlType() { + return 'tokenizer'; + } + + private function getDatasource() { + $datasource = new PhabricatorProjectOrUserDatasource(); + + if ($this->getViewer()) { + $datasource->setViewer($this->getViewer()); + } + + return $datasource; + } + + protected function getPHUIXControlSpecification() { + $template = id(new AphrontTokenizerTemplateView()) + ->setViewer($this->getViewer()); + + $template_markup = $template->render(); + $datasource = $this->getDatasource(); + + return array( + 'markup' => (string)hsprintf('%s', $template_markup), + 'config' => array( + 'src' => $datasource->getDatasourceURI(), + 'browseURI' => $datasource->getBrowseURI(), + 'placeholder' => $datasource->getPlaceholderText(), + 'limit' => $datasource->getLimit(), + ), + 'value' => null, + ); + } + + public function getRuleViewLabel() { + return pht('Remove subscribers'); + } + + public function getRuleViewDescription($value) { + return pht( + 'Remove subscribers: %s.', + phutil_tag( + 'strong', + array(), + $this->getViewer() + ->renderHandleList($value) + ->setAsInline(true) + ->render())); + } + + public function getRuleViewIcon($value) { + return id(new PHUIIconView()) + ->setIcon('fa-users', 'red'); + } + +}