mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-22 21:40:55 +01:00
Conpherence - add per thread notification setting
Summary: Introduces a new settings panel for Conpherence specific settings. Test Plan: started a thread with a test user, thus two participants total. Replied to conpherence, toggling notification settings in between. Verified 1 or 2 emails were sent as appropos to the current toggle. Toggled global setting and verified setting was updated in conpherences where nothing was specified. Verified setting conpherence setting overrides global setting. Reviewers: epriestley, chad Reviewed By: epriestley CC: aran, Korvin Maniphest Tasks: T2521 Differential Revision: https://secure.phabricator.com/D5391
This commit is contained in:
parent
8a0fccf97a
commit
23dc686045
14 changed files with 284 additions and 17 deletions
2
resources/sql/patches/20130319.conpherence.sql
Normal file
2
resources/sql/patches/20130319.conpherence.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_conpherence.conpherence_participant
|
||||
ADD settings LONGTEXT NOT NULL COLLATE utf8_bin AFTER behindTransactionPHID;
|
|
@ -840,7 +840,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'conpherence-widget-pane-css' =>
|
||||
array(
|
||||
'uri' => '/res/0e4a8ded/rsrc/css/application/conpherence/widget-pane.css',
|
||||
'uri' => '/res/bd8ca250/rsrc/css/application/conpherence/widget-pane.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -1206,7 +1206,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-behavior-conpherence-pontificate' =>
|
||||
array(
|
||||
'uri' => '/res/15263692/rsrc/js/application/conpherence/behavior-pontificate.js',
|
||||
'uri' => '/res/fe634761/rsrc/js/application/conpherence/behavior-pontificate.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -1219,13 +1219,16 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-behavior-conpherence-widget-pane' =>
|
||||
array(
|
||||
'uri' => '/res/43a0fe1b/rsrc/js/application/conpherence/behavior-widget-pane.js',
|
||||
'uri' => '/res/52b80633/rsrc/js/application/conpherence/behavior-widget-pane.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
1 => 'javelin-dom',
|
||||
2 => 'javelin-stratcom',
|
||||
3 => 'javelin-workflow',
|
||||
4 => 'javelin-util',
|
||||
5 => 'phabricator-notification',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/conpherence/behavior-widget-pane.js',
|
||||
),
|
||||
|
|
|
@ -240,6 +240,7 @@ phutil_register_library_map(array(
|
|||
'ConpherencePeopleMenuEventListener' => 'applications/conpherence/events/ConpherencePeopleMenuEventListener.php',
|
||||
'ConpherencePontificateControl' => 'applications/conpherence/view/ConpherencePontificateControl.php',
|
||||
'ConpherenceReplyHandler' => 'applications/conpherence/mail/ConpherenceReplyHandler.php',
|
||||
'ConpherenceSettings' => 'applications/conpherence/constants/ConpherenceSettings.php',
|
||||
'ConpherenceThread' => 'applications/conpherence/storage/ConpherenceThread.php',
|
||||
'ConpherenceThreadQuery' => 'applications/conpherence/query/ConpherenceThreadQuery.php',
|
||||
'ConpherenceTransaction' => 'applications/conpherence/storage/ConpherenceTransaction.php',
|
||||
|
@ -1301,6 +1302,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php',
|
||||
'PhabricatorSettingsPanelAccount' => 'applications/settings/panel/PhabricatorSettingsPanelAccount.php',
|
||||
'PhabricatorSettingsPanelConduit' => 'applications/settings/panel/PhabricatorSettingsPanelConduit.php',
|
||||
'PhabricatorSettingsPanelConpherencePreferences' => 'applications/settings/panel/PhabricatorSettingsPanelConpherencePreferences.php',
|
||||
'PhabricatorSettingsPanelDiffPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDiffPreferences.php',
|
||||
'PhabricatorSettingsPanelDisplayPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDisplayPreferences.php',
|
||||
'PhabricatorSettingsPanelEmailAddresses' => 'applications/settings/panel/PhabricatorSettingsPanelEmailAddresses.php',
|
||||
|
@ -1907,6 +1909,7 @@ phutil_register_library_map(array(
|
|||
'ConpherencePeopleMenuEventListener' => 'PhutilEventListener',
|
||||
'ConpherencePontificateControl' => 'AphrontFormControl',
|
||||
'ConpherenceReplyHandler' => 'PhabricatorMailReplyHandler',
|
||||
'ConpherenceSettings' => 'ConpherenceConstants',
|
||||
'ConpherenceThread' =>
|
||||
array(
|
||||
0 => 'ConpherenceDAO',
|
||||
|
@ -2907,6 +2910,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSettingsMainController' => 'PhabricatorController',
|
||||
'PhabricatorSettingsPanelAccount' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSettingsPanelConduit' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSettingsPanelConpherencePreferences' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSettingsPanelDiffPreferences' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSettingsPanelDisplayPreferences' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSettingsPanelEmailAddresses' => 'PhabricatorSettingsPanel',
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
final class ConpherenceSettings extends ConpherenceConstants {
|
||||
|
||||
const EMAIL_ALWAYS = 0;
|
||||
const NOTIFICATIONS_ONLY = 1;
|
||||
|
||||
public static function getHumanString($constant) {
|
||||
$string = pht('Unknown setting.');
|
||||
|
||||
switch ($constant) {
|
||||
case self::EMAIL_ALWAYS:
|
||||
$string = pht('Email me every update.');
|
||||
break;
|
||||
case self::NOTIFICATIONS_ONLY:
|
||||
$string = pht('Notifications only.');
|
||||
break;
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
}
|
|
@ -60,6 +60,17 @@ final class ConpherenceUpdateController extends
|
|||
$conpherence,
|
||||
$message);
|
||||
break;
|
||||
case 'notifications':
|
||||
$notifications = $request->getStr('notifications');
|
||||
$participant = $conpherence->getParticipant($user->getPHID());
|
||||
$participant->setSettings(array('notifications' => $notifications));
|
||||
$participant->save();
|
||||
$result = pht(
|
||||
'Updated notification settings to "%s".',
|
||||
ConpherenceSettings::getHumanString($notifications));
|
||||
return id(new AphrontAjaxResponse())
|
||||
->setContent($result);
|
||||
break;
|
||||
case 'metadata':
|
||||
$xactions = array();
|
||||
$top = $request->getInt('image_y');
|
||||
|
|
|
@ -8,6 +8,15 @@ final class ConpherenceWidgetController extends
|
|||
|
||||
private $conpherenceID;
|
||||
private $conpherence;
|
||||
private $userPreferences;
|
||||
|
||||
public function setUserPreferences(PhabricatorUserPreferences $pref) {
|
||||
$this->userPreferences = $pref;
|
||||
return $this;
|
||||
}
|
||||
public function getUserPreferences() {
|
||||
return $this->userPreferences;
|
||||
}
|
||||
|
||||
public function setConpherence(ConpherenceThread $conpherence) {
|
||||
$this->conpherence = $conpherence;
|
||||
|
@ -44,6 +53,8 @@ final class ConpherenceWidgetController extends
|
|||
->executeOne();
|
||||
$this->setConpherence($conpherence);
|
||||
|
||||
$this->setUserPreferences($user->loadPreferences());
|
||||
|
||||
$widgets = $this->renderWidgetPaneContent();
|
||||
$content = $widgets;
|
||||
return id(new AphrontAjaxResponse())->setContent($content);
|
||||
|
@ -57,8 +68,8 @@ final class ConpherenceWidgetController extends
|
|||
Javelin::initBehavior(
|
||||
'conpherence-widget-pane',
|
||||
array(
|
||||
'form_pane' => 'conpherence-form',
|
||||
'file_widget' => 'widgets-files',
|
||||
'settings_widget' => 'widgets-settings',
|
||||
'widgetRegistery' => array(
|
||||
'widgets-conpherence-list' => $cant_toggle,
|
||||
'widgets-conversation' => $cant_toggle,
|
||||
|
@ -201,7 +212,63 @@ final class ConpherenceWidgetController extends
|
|||
}
|
||||
|
||||
private function renderSettingsWidgetPaneContent() {
|
||||
return 'TODO - settings';
|
||||
$user = $this->getRequest()->getUser();
|
||||
$conpherence = $this->getConpherence();
|
||||
$participants = $conpherence->getParticipants();
|
||||
$participant = $participants[$user->getPHID()];
|
||||
$default = ConpherenceSettings::EMAIL_ALWAYS;
|
||||
$preference = $this->getUserPreferences();
|
||||
if ($preference) {
|
||||
$default = $preference->getPreference(
|
||||
PhabricatorUserPreferences::PREFERENCE_CONPH_NOTIFICATIONS,
|
||||
ConpherenceSettings::EMAIL_ALWAYS);
|
||||
}
|
||||
$settings = $participant->getSettings();
|
||||
$notifications = idx(
|
||||
$settings,
|
||||
'notifications',
|
||||
$default);
|
||||
$options = id(new AphrontFormRadioButtonControl())
|
||||
->addButton(
|
||||
ConpherenceSettings::EMAIL_ALWAYS,
|
||||
ConpherenceSettings::getHumanString(
|
||||
ConpherenceSettings::EMAIL_ALWAYS),
|
||||
'')
|
||||
->addButton(
|
||||
ConpherenceSettings::NOTIFICATIONS_ONLY,
|
||||
ConpherenceSettings::getHumanString(
|
||||
ConpherenceSettings::NOTIFICATIONS_ONLY),
|
||||
'')
|
||||
->setName('notifications')
|
||||
->setValue($notifications);
|
||||
|
||||
$href = $this->getApplicationURI(
|
||||
'update/'.$conpherence->getID().'/');
|
||||
$layout = array(
|
||||
$options,
|
||||
phutil_tag(
|
||||
'input',
|
||||
array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'action',
|
||||
'value' => 'notifications'
|
||||
)),
|
||||
javelin_tag(
|
||||
'button',
|
||||
array(
|
||||
'sigil' => 'notifications-update',
|
||||
'class' => 'notifications-update grey',
|
||||
),
|
||||
pht('Update Notifications'))
|
||||
);
|
||||
|
||||
return phabricator_form(
|
||||
$user,
|
||||
array(
|
||||
'method' => 'POST',
|
||||
'action' => $href,
|
||||
),
|
||||
$layout);
|
||||
}
|
||||
|
||||
private function renderCalendarWidgetPaneContent() {
|
||||
|
|
|
@ -159,13 +159,15 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
|
|||
}
|
||||
break;
|
||||
case ConpherenceTransactionType::TYPE_PARTICIPANTS:
|
||||
$participants = array();
|
||||
foreach ($xaction->getNewValue() as $participant) {
|
||||
if ($participant == $this->getActor()->getPHID()) {
|
||||
$status = ConpherenceParticipationStatus::UP_TO_DATE;
|
||||
} else {
|
||||
$status = ConpherenceParticipationStatus::BEHIND;
|
||||
}
|
||||
id(new ConpherenceParticipant())
|
||||
$participants[] =
|
||||
id(new ConpherenceParticipant())
|
||||
->setConpherencePHID($object->getPHID())
|
||||
->setParticipantPHID($participant)
|
||||
->setParticipationStatus($status)
|
||||
|
@ -173,6 +175,8 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
|
|||
->setBehindTransactionPHID($xaction->getPHID())
|
||||
->save();
|
||||
}
|
||||
$participants = mpull($participants, null, 'getParticipantPHID');
|
||||
$object->attachParticipants($participants);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -221,7 +225,28 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
|
|||
|
||||
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||
$participants = $object->getParticipants();
|
||||
return array_keys($participants);
|
||||
$preferences = id(new PhabricatorUserPreferences())
|
||||
->loadAllWhere('userPHID in (%Ls)', array_keys($participants));
|
||||
$preferences = mpull($preferences, null, 'getUserPHID');
|
||||
$to_phids = array();
|
||||
foreach ($participants as $phid => $participant) {
|
||||
$default = ConpherenceSettings::EMAIL_ALWAYS;
|
||||
$preference = idx($preferences, $phid);
|
||||
if ($preference) {
|
||||
$default = $preference->getPreference(
|
||||
PhabricatorUserPreferences::PREFERENCE_CONPH_NOTIFICATIONS,
|
||||
ConpherenceSettings::EMAIL_ALWAYS);
|
||||
}
|
||||
$settings = $participant->getSettings();
|
||||
$notifications = idx(
|
||||
$settings,
|
||||
'notifications',
|
||||
$default);
|
||||
if ($notifications == ConpherenceSettings::EMAIL_ALWAYS) {
|
||||
$to_phids[] = $phid;
|
||||
}
|
||||
}
|
||||
return $to_phids;
|
||||
}
|
||||
|
||||
protected function getMailCC(PhabricatorLiskDAO $object) {
|
||||
|
@ -251,5 +276,4 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
|
|||
protected function supportsSearch() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,19 @@ final class ConpherenceParticipant extends ConpherenceDAO {
|
|||
protected $participationStatus;
|
||||
protected $behindTransactionPHID;
|
||||
protected $dateTouched;
|
||||
protected $settings = array();
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_SERIALIZATION => array(
|
||||
'settings' => self::SERIALIZATION_JSON,
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function getSettings() {
|
||||
return nonempty($this->settings, array());
|
||||
}
|
||||
|
||||
public function markUpToDate(ConpherenceTransaction $xaction) {
|
||||
if (!$this->isUpToDate()) {
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorSettingsPanelConpherencePreferences
|
||||
extends PhabricatorSettingsPanel {
|
||||
|
||||
public function isEnabled() {
|
||||
// TODO - epriestley - resolve isBeta and isInstalled for
|
||||
// PhabricatorApplication
|
||||
$app = PhabricatorApplication::getByClass(
|
||||
'PhabricatorApplicationConpherence');
|
||||
$is_prod = !$app->isBeta();
|
||||
$allow_beta =
|
||||
PhabricatorEnv::getEnvConfig('phabricator.show-beta-applications');
|
||||
return ($is_prod || $allow_beta) && $app->isInstalled();
|
||||
}
|
||||
|
||||
public function getPanelKey() {
|
||||
return 'conpherence';
|
||||
}
|
||||
|
||||
public function getPanelName() {
|
||||
return pht('Conpherence Preferences');
|
||||
}
|
||||
|
||||
public function getPanelGroup() {
|
||||
return pht('Application Settings');
|
||||
}
|
||||
|
||||
public function processRequest(AphrontRequest $request) {
|
||||
$user = $request->getUser();
|
||||
$preferences = $user->loadPreferences();
|
||||
|
||||
$pref = PhabricatorUserPreferences::PREFERENCE_CONPH_NOTIFICATIONS;
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$notifications = $request->getInt($pref);
|
||||
$preferences->setPreference($pref, $notifications);
|
||||
$preferences->save();
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($this->getPanelURI('?saved=true'));
|
||||
}
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($user)
|
||||
->appendChild(
|
||||
id(new AphrontFormSelectControl())
|
||||
->setLabel(pht('Conpherence Notifications'))
|
||||
->setName($pref)
|
||||
->setValue($preferences->getPreference($pref))
|
||||
->setOptions(
|
||||
array(
|
||||
ConpherenceSettings::EMAIL_ALWAYS
|
||||
=> pht('Email Always'),
|
||||
ConpherenceSettings::NOTIFICATIONS_ONLY
|
||||
=> pht('Notifications Only'),
|
||||
))
|
||||
->setCaption(
|
||||
pht('Should Conpherence send emails for updates or '.
|
||||
'notifications only? This global setting can be overridden '.
|
||||
'on a per-thread basis within Conpherence.')))
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue(pht('Save Preferences')));
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setHeader(pht('Conpherence Preferences'));
|
||||
$panel->appendChild($form);
|
||||
$panel->setNoBackground();
|
||||
|
||||
$error_view = null;
|
||||
if ($request->getBool('saved')) {
|
||||
$error_view = id(new AphrontErrorView())
|
||||
->setTitle(pht('Preferences Saved'))
|
||||
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
|
||||
->setErrors(array(pht('Your preferences have been saved.')));
|
||||
}
|
||||
|
||||
return array(
|
||||
$error_view,
|
||||
$panel,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,8 @@ final class PhabricatorUserPreferences extends PhabricatorUserDAO {
|
|||
|
||||
const PREFERENCE_DIFF_FILETREE = 'diff-filetree';
|
||||
|
||||
const PREFERENCE_CONPH_NOTIFICATIONS = 'conph-notifications';
|
||||
|
||||
protected $userPHID;
|
||||
protected $preferences = array();
|
||||
|
||||
|
|
|
@ -1180,7 +1180,11 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
|||
'20130319.phabricatorfileexplicitupload.sql' => array(
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath(
|
||||
'20130319.phabricatorfileexplicitupload.sql'),
|
||||
'20130319.phabricatorfileexplicitupload.sql')
|
||||
),
|
||||
'20130319.conpherence.sql' => array(
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20130319.conpherence.sql'),
|
||||
),
|
||||
'20130320.phlux.sql' => array(
|
||||
'type' => 'sql',
|
||||
|
|
|
@ -26,6 +26,11 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.conpherence-widget-pane .aphront-form-inset {
|
||||
border: 0;
|
||||
background: url('/rsrc/image/texture/dust_background.jpg');
|
||||
}
|
||||
|
||||
.conpherence-widget-pane .widgets-header {
|
||||
background-color: #d8dce2;
|
||||
box-shadow: 0px 2px 2px rgba(0,0,0,0.15);
|
||||
|
@ -186,3 +191,8 @@
|
|||
.conpherence-widget-pane .phabricator-remarkup-embed-layout-link {
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
/* settings widget */
|
||||
.conpherence-widget-pane .notifications-update {
|
||||
margin: 2px 0px 0px 8px;
|
||||
}
|
||||
|
|
|
@ -50,13 +50,6 @@ JX.behavior('conpherence-pontificate', function(config) {
|
|||
.start();
|
||||
};
|
||||
|
||||
JX.DOM.listen(
|
||||
root,
|
||||
['submit', 'didSyntheticSubmit'],
|
||||
null,
|
||||
onsubmit
|
||||
);
|
||||
|
||||
JX.DOM.listen(
|
||||
root,
|
||||
['click'],
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
/**
|
||||
* @provides javelin-behavior-conpherence-widget-pane
|
||||
* @requires javelin-behavior
|
||||
* javelin-dom
|
||||
* javelin-stratcom
|
||||
* javelin-workflow
|
||||
* javelin-util
|
||||
* phabricator-notification
|
||||
* @provides javelin-behavior-conpherence-widget-pane
|
||||
*/
|
||||
|
||||
JX.behavior('conpherence-widget-pane', function(config) {
|
||||
|
@ -36,4 +39,29 @@ JX.behavior('conpherence-widget-pane', function(config) {
|
|||
}
|
||||
);
|
||||
|
||||
var settingsRoot = JX.$(config.settings_widget);
|
||||
|
||||
var onsubmitSettings = function (e) {
|
||||
e.kill();
|
||||
var form = JX.DOM.find(settingsRoot, 'form');
|
||||
var button = JX.DOM.find(form, 'button');
|
||||
JX.Workflow.newFromForm(form)
|
||||
.setHandler(JX.bind(this, function (r) {
|
||||
new JX.Notification()
|
||||
.setDuration(6000)
|
||||
.setContent(r)
|
||||
.show();
|
||||
button.disabled = '';
|
||||
JX.DOM.alterClass(button, 'disabled', false);
|
||||
}))
|
||||
.start();
|
||||
};
|
||||
|
||||
JX.DOM.listen(
|
||||
settingsRoot,
|
||||
['click'],
|
||||
'notifications-update',
|
||||
onsubmitSettings
|
||||
);
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue