1
0
Fork 0
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:
Bob Trahan 2013-03-26 13:30:35 -07:00
parent 8a0fccf97a
commit 23dc686045
14 changed files with 284 additions and 17 deletions

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_conpherence.conpherence_participant
ADD settings LONGTEXT NOT NULL COLLATE utf8_bin AFTER behindTransactionPHID;

View file

@ -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',
),

View file

@ -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',

View file

@ -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;
}
}

View file

@ -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');

View file

@ -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() {

View file

@ -159,12 +159,14 @@ 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;
}
$participants[] =
id(new ConpherenceParticipant())
->setConpherencePHID($object->getPHID())
->setParticipantPHID($participant)
@ -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;
}
}

View file

@ -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()) {

View file

@ -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,
);
}
}

View file

@ -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();

View file

@ -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',

View file

@ -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;
}

View file

@ -50,13 +50,6 @@ JX.behavior('conpherence-pontificate', function(config) {
.start();
};
JX.DOM.listen(
root,
['submit', 'didSyntheticSubmit'],
null,
onsubmit
);
JX.DOM.listen(
root,
['click'],

View file

@ -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
);
});