Gitter migration: Point people to app.gitter.im (rollout pt. 1)
[gitter.git] / public / js / views / modals / notification-settings-view.js
blob4d71b71d65811779713e24111e6f411838f81234
1 'use strict';
3 var Marionette = require('backbone.marionette');
4 var _ = require('lodash');
5 var apiClient = require('../../components/api-client');
6 var ModalView = require('./modal');
7 var template = require('./tmpl/notification-settings-view.hbs');
8 var userNotifications = require('../../components/user-notifications');
9 var FeaturesView = require('./notification-features-collection-view');
11 var OPTIONS = {
12 all: 'All: Notify me for all messages',
13 announcement: 'Announcements: Notify me for mentions/announcements (email for all messages)',
14 mute: "Mute: Notify me only when I'm directly mentioned"
17 var View = Marionette.LayoutView.extend({
18 template: template,
19 events: {
20 'click #close-settings': 'destroySettings',
21 'change #notification-options': 'formChange'
23 modelEvents: {
24 change: 'update'
26 ui: {
27 options: '#notification-options',
28 nonstandard: '#nonstandard',
29 notifyFeatures: '#notify-features'
31 regions: {
32 notifyFeatures: '#notify-features'
35 initialize: function() {
36 // TODO: this should go to the userRoom endpoint as a get
37 // or better yet should be a live field on the room
38 apiClient.userRoom
39 .get('/settings/notifications')
40 .bind(this)
41 .then(function(settings) {
42 this.model.set(settings);
43 });
45 this.listenTo(this, 'menuItemClicked', this.menuItemClicked);
48 getNotificationOption: function() {
49 var model = this.model;
51 if (!model.attributes.hasOwnProperty('mode')) {
52 // Not yet loaded...
53 return null;
55 var value = model.get('mode');
56 var lurk = model.get('lurk');
58 var nonStandard;
60 var defaultDescription =
61 'Legacy setting: ' +
62 value +
63 ' mode, with ' +
64 (lurk ? 'unread item count off' : 'unread item count on');
66 switch (value) {
67 case 'all':
68 nonStandard = lurk === true;
69 return {
70 selectValue: 'all',
71 nonStandard: nonStandard,
72 description: nonStandard ? defaultDescription : null
75 case 'announcement':
76 case 'mention':
77 nonStandard = lurk === true;
79 return {
80 selectValue: 'announcement',
81 nonStandard: nonStandard,
82 description: nonStandard ? defaultDescription : null
85 case 'mute':
86 nonStandard = lurk === false;
88 return {
89 selectValue: 'mute',
90 nonStandard: nonStandard,
91 description: nonStandard ? defaultDescription : null
94 default:
95 return {
96 selectValue: 'mute',
97 nonStandard: true,
98 description: 'Custom legacy setting (details below)'
103 update: function() {
104 var val = this.getNotificationOption();
106 if (val) {
107 if (val.nonStandard) {
108 this.ui.nonstandard.show();
109 } else {
110 this.ui.nonstandard.hide();
113 var isDefault = this.model.get('default');
115 if (isDefault) {
116 this.setOption('default');
117 } else {
118 if (val.nonStandard) {
119 this.setOption('', val.description);
120 } else {
121 this.setOption(val.selectValue);
124 } else {
125 this.setOption('', 'Please wait...');
126 this.ui.nonstandard.hide();
129 var count = 0;
130 if (this.featuresView) {
131 count = this.featuresView.resetFromHash(this.model.attributes);
132 } else {
133 count = 0;
136 if (count > 0) {
137 this.ui.notifyFeatures.show();
138 } else {
139 this.ui.notifyFeatures.hide();
143 setOption: function(val, text) {
144 var selectInput = this.ui.options;
145 selectInput.empty();
146 var found = false;
148 var defaultOptgroup = document.createElement('optgroup');
149 defaultOptgroup.label = 'Use Default';
150 selectInput.append(defaultOptgroup);
152 var defaultOption = document.createElement('option');
153 defaultOption.value = 'default';
154 defaultOption.textContent = this.getDefaulDescription();
155 if (val === 'default') {
156 defaultOption.selected = true;
157 found = true;
159 defaultOptgroup.appendChild(defaultOption);
161 var overrideOptGroup = document.createElement('optgroup');
162 overrideOptGroup.label = 'Override';
163 selectInput.append(overrideOptGroup);
165 Object.keys(OPTIONS).forEach(function(key) {
166 var text = OPTIONS[key];
168 var option = document.createElement('option');
169 option.value = key;
170 option.textContent = text;
171 var selected = key === val;
172 option.selected = selected;
173 if (selected) {
174 found = true;
176 overrideOptGroup.appendChild(option);
179 if (!found) {
180 var option = document.createElement('option');
181 option.value = val;
182 option.textContent = text;
183 option.selected = true;
184 option.style.display = 'none';
185 overrideOptGroup.appendChild(option);
189 getDefaulDescription: function() {
190 var model = this.model;
191 var defaultSettings = model.get('defaultSettings');
192 if (!defaultSettings) return 'Default settings';
194 if (!defaultSettings.mode || !OPTIONS[defaultSettings.mode]) return 'Legacy settings';
195 return OPTIONS[defaultSettings.mode];
198 onRender: function() {
199 this.featuresView = new FeaturesView({});
200 this.getRegion('notifyFeatures').show(this.featuresView);
201 this.update();
204 formChange: function(e) {
205 if (e) e.preventDefault();
206 var mode = this.ui.options.val();
207 var oldIsDefault = this.model.get('default');
209 var effectiveMode = mode;
210 if (mode === 'default') {
211 var defaultSettings = this.model.get('defaultSettings');
212 effectiveMode = defaultSettings && defaultSettings.mode;
214 this.featuresView.resetFromMode(effectiveMode);
216 var noChange;
217 if (oldIsDefault) {
218 noChange = mode === 'default';
219 } else {
220 noChange = mode === this.model.get('mode');
223 this.dialog.toggleButtonClass('apply', 'modal--default__footer__btn--neutral', noChange);
224 this.dialog.toggleButtonClass('apply', 'modal--default__footer__btn', !noChange);
227 destroySettings: function() {
228 this.dialog.hide();
229 this.dialog = null;
232 serializeData: function() {
233 return {
234 notificationsBlocked: userNotifications.isAccessDenied()
238 menuItemClicked: function(button) {
239 switch (button) {
240 case 'set-defaults':
241 window.location.href = '#notification-defaults';
242 break;
243 case 'apply':
244 this.applyChangeAndClose();
245 break;
249 applyChangeAndClose: function() {
250 var mode = this.ui.options.val();
251 // TODO: this should go to the userRoom endpoint as a patch
252 apiClient.userRoom
253 .put('/settings/notifications', { mode: mode })
254 .bind(this)
255 .then(function() {
256 this.dialog.hide();
257 this.dialog = null;
262 module.exports = ModalView.extend({
263 initialize: function(options) {
264 options = _.extend(
266 title: 'Notification Settings',
267 menuItems: [
269 action: 'set-defaults',
270 pull: 'left',
271 text: 'Configure Defaults',
272 className: 'modal--default__footer__link'
275 action: 'apply',
276 pull: 'right',
277 text: 'Apply',
278 className: 'modal--default__footer__btn--neutral'
282 options
285 ModalView.prototype.initialize.call(this, options);
286 this.view = new View(options);