New UI for the notification settings
authorAlexander Ebert <ebert@woltlab.com>
Tue, 23 Jun 2020 16:49:08 +0000 (18:49 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Tue, 23 Jun 2020 16:49:08 +0000 (18:49 +0200)
com.woltlab.wcf/templates/notificationSettings.tpl
wcfsetup/install/files/js/WoltLabSuite/Core/Controller/User/Notification/Settings.js
wcfsetup/install/files/style/ui/notification.scss [new file with mode: 0644]

index cfb7071b4a432716cbcab4474175601524e81e9c..7f9e78f7b06a4e8f3250d60f2d19c60c3d2d29cf 100644 (file)
 {/if}
 
 <form method="post" action="{link controller='NotificationSettings'}{/link}" id="notificationSettings">
-       {foreach from=$events key='eventCategory' item='eventList'}
-               <section class="section">
-                       <h2 class="sectionTitle">{lang}wcf.user.notification.{$eventCategory}{/lang}</h2>
-                       
-                       <dl>
+       <div class="section">
+               {foreach from=$events key='eventCategory' item='eventList'}
+                       <div class="notificationSettings">
+                               <div class="notificationSettingsCategory">
+                                       <div class="notificationSettingsEvent">{lang}wcf.user.notification.{$eventCategory}{/lang}</div>
+                                       <div class="notificationSettingsState">Aktiv</div>
+                                       <div class="notificationSettingsEmail">E-Mail</div>
+                               </div>
                                {foreach from=$eventList item=event}
-                                       <dt>{lang}wcf.user.notification.{$event->objectType}.{$event->eventName}{/lang}</dt>
-                                       <dd>
-                                               <ol class="flexibleButtonGroup" data-object-id="{@$event->eventID}">
-                                                       <li>
-                                                               <input type="radio" id="settings_{@$event->eventID}_disabled" name="settings[{@$event->eventID}][enabled]" value="0"{if $settings[$event->eventID][enabled]|empty} checked{/if}>
-                                                               <label for="settings_{@$event->eventID}_disabled" class="red">
-                                                                       <span class="icon icon16 fa-times"></span>
-                                                                       {lang}wcf.user.notification.notifications.disabled{/lang}
-                                                               </label>
-                                                       </li>
-                                                       <li class="spaceAfter">
-                                                               <input type="radio" id="settings_{@$event->eventID}_enabled" name="settings[{@$event->eventID}][enabled]" value="1"{if !$settings[$event->eventID][enabled]|empty} checked{/if}>
-                                                               <label for="settings_{@$event->eventID}_enabled" class="green">
-                                                                       <span class="icon icon16 fa-bell"></span>
-                                                                       {lang}wcf.user.notification.notifications.enabled{/lang}
-                                                               </label>
-                                                       </li>
+                                       <div class="notificationSettingsItem">
+                                               <div class="notificationSettingsEvent">
+                                                       <label for="settings_{@$event->eventID}">{lang}wcf.user.notification.{$event->objectType}.{$event->eventName}{/lang}</label>
+                                               </div>
+                                               <div class="notificationSettingsState">
+                                                       <label>
+                                                               <input type="checkbox" id="settings_{@$event->eventID}" name="settings[{@$event->eventID}][enabled]" value="1"{if !$settings[$event->eventID][enabled]|empty} checked{/if}>
+                                                               <span class="icon icon24 fa-bell green pointer"></span>
+                                                               <span class="icon icon24 fa-bell-slash red pointer"></span>
+                                                       </label>
+                                               </div>
+                                               <div class="notificationSettingsEmail">
                                                        {if $event->supportsEmailNotification()}
-                                                               <li class="notificationSettingsEmail{if !$settings[$event->eventID][enabled]|empty} active{/if}">
-                                                                       <input type="hidden" id="settings_{$event->eventID}_mailNotificationType" name="settings[{@$event->eventID}][mailNotificationType]" value="{$settings[$event->eventID][mailNotificationType]}">
-                                                                       <a{if $settings[$event->eventID][mailNotificationType] !== 'none'} class="active yellow"{/if}>
-                                                                               <span class="icon icon16 fa-envelope-o"></span>
-                                                                               <span class="title">{lang}wcf.user.notification.mailNotificationType.{$settings[$event->eventID][mailNotificationType]}{/lang}</span>
-                                                                               <span class="icon icon16 fa-caret-down"></span>
-                                                                       </a>
-                                                               </li>
+                                                               <input type="hidden" id="settings_{$event->eventID}_mailNotificationType" name="settings[{@$event->eventID}][mailNotificationType]" value="{$settings[$event->eventID][mailNotificationType]}">
+                                                               <a href="#" class="notificationSettingsEmailType" role="button" aria-label="{lang}wcf.user.notification.mailNotificationType.{@$settings[$event->eventID][mailNotificationType]}{/lang}" data-object-id="{@$event->eventID}">
+                                                                       {if $settings[$event->eventID][mailNotificationType] === 'none'}
+                                                                               <span class="icon icon24 fa-times red jsIconNotificationSettingsEmailType"></span>
+                                                                       {else}
+                                                                               <span class="icon icon24 {if $settings[$event->eventID][mailNotificationType] === 'instant'}fa-flash{else}fa-clock-o{/if} green jsIconNotificationSettingsEmailType"></span>
+                                                                       {/if}
+                                                                       <span class="icon icon16 fa-caret-down"></span>
+                                                               </a>
                                                        {/if}
-                                               </ol>
-                                       </dd>
+                                               </div>
+                                       </div>
                                {/foreach}
-                       </dl>
-               </section>
-       {/foreach}
+                       </div>
+               {/foreach}
+       </div>
        
        {event name='sections'}
        
@@ -72,7 +71,7 @@
                        'wcf.user.notification.mailNotificationType.none': '{lang}wcf.user.notification.mailNotificationType.none{/lang}'
                });
                
-               ControllerUserNotificationSettings.setup();
+               ControllerUserNotificationSettings.init();
        });
 </script>
 
index 0afac53be570da1079a2cf7906ce128fccb1fdd3..7861c4fdd0257a9c3dfaaa74b5e09a1dedf1bbec 100644 (file)
 /**
  * Handles email notification type for user notification settings.
- * 
- * @author     Alexander Ebert
- * @copyright  2001-2019 WoltLab GmbH
- * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module     WoltLabSuite/Core/Controller/User/Notification/Settings
+ *
+ * @author      Alexander Ebert
+ * @copyright   2001-2020 WoltLab GmbH
+ * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module      WoltLabSuite/Core/Controller/User/Notification/Settings
  */
-define(['Dictionary', 'Language', 'Dom/Traverse', 'Ui/SimpleDropdown'], function(Dictionary, Language, DomTraverse, UiSimpleDropdown) {
-       "use strict";
+define(['Language', 'Ui/ReusableDropdown'], function (Language, UiReusableDropdown) {
+       'use strict';
        
        if (!COMPILER_TARGET_DEFAULT) {
-               var Fake = function() {};
-               Fake.prototype = {
-                       setup: function() {},
-                       _initGroup: function() {},
-                       _click: function() {},
-                       _createDropdown: function() {},
-                       _selectType: function() {}
-               };
-               return Fake;
+               return function () {};
        }
        
-       var _data = new Dictionary();
-       
-       var _callbackClick = null;
-       var _callbackSelectType = null;
+       var _dropDownMenu = null;
+       var _objectId = null;
        
        /**
         * @exports     WoltLabSuite/Core/Controller/User/Notification/Settings
         */
-       var ControllerUserNotificationSettings = {
+       return {
                /**
                 * Binds event listeners for all notifications supporting emails.
                 */
-               setup: function() {
-                       _callbackClick = this._click.bind(this);
-                       _callbackSelectType = this._selectType.bind(this);
-                       
-                       var group, mailSetting, groups = elBySelAll('#notificationSettings .flexibleButtonGroup');
-                       for (var i = 0, length = groups.length; i < length; i++) {
-                               group = groups[i];
-                               
-                               mailSetting = elBySel('.notificationSettingsEmail', group);
-                               if (mailSetting === null) {
-                                       continue;
-                               }
-                               
-                               this._initGroup(group, mailSetting);
-                       }
+               init: function () {
+                       elBySelAll('.notificationSettingsEmailType', undefined, (function (button) {
+                               button.addEventListener('click', this._click.bind(this));
+                       }).bind(this));
                },
                
                /**
-                * Initializes a setting.
-                * 
-                * @param       {Element}       group           button group element
-                * @param       {Element}       mailSetting     mail settings element
+                * @param       {Event} event           event object
                 */
-               _initGroup: function(group, mailSetting) {
-                       var groupId = ~~elData(group, 'object-id');
+               _click: function (event) {
+                       event.preventDefault();
+                       event.stopPropagation();
                        
-                       var disabledNotification = elById('settings_' + groupId + '_disabled');
-                       disabledNotification.addEventListener(WCF_CLICK_EVENT, function() { mailSetting.classList.remove('active'); });
-                       var enabledNotification = elById('settings_' + groupId + '_enabled');
-                       enabledNotification.addEventListener(WCF_CLICK_EVENT, function() { mailSetting.classList.add('active'); });
+                       var button = event.currentTarget;
+                       _objectId = ~~elData(button, 'object-id');
                        
-                       var mailValue = DomTraverse.childByTag(mailSetting, 'INPUT');
+                       this._createDropDown();
                        
-                       var button = DomTraverse.childByTag(mailSetting, 'A');
-                       elData(button, 'object-id', groupId);
-                       button.addEventListener(WCF_CLICK_EVENT, _callbackClick);
+                       this._setCurrentEmailType(this._getEmailTypeInputElement().value);
                        
-                       _data.set(groupId, {
-                               button: button,
-                               dropdownMenu: null,
-                               mailSetting: mailSetting,
-                               mailValue: mailValue
-                       });
+                       this._showDropDown(button);
                },
                
-               /**
-                * Creates and displays the email type dropdown.
-                * 
-                * @param       {Object}        event           event object
-                */
-               _click: function(event) {
-                       event.preventDefault();
-                       
-                       var button = event.currentTarget;
-                       var objectId = ~~elData(button, 'object-id');
-                       var data = _data.get(objectId);
-                       if (data.dropdownMenu === null) {
-                               data.dropdownMenu = this._createDropdown(objectId, data.mailValue.value);
-                               
-                               button.parentNode.classList.add('dropdown');
-                               button.parentNode.appendChild(data.dropdownMenu);
-                               
-                               UiSimpleDropdown.init(button, event);
+               _createDropDown: function () {
+                       if (_dropDownMenu !== null) {
+                               return;
                        }
-                       else {
-                               var items = DomTraverse.childrenByTag(data.dropdownMenu, 'LI'), value = data.mailValue.value;
-                               for (var i = 0; i < 4; i++) {
-                                       items[i].classList[(elData(items[i], 'value') === value) ? 'add' : 'remove']('active');
-                               }
-                       }
-               },
-               
-               /**
-                * Creates the email type dropdown.
-                * 
-                * @param       {int}           objectId        notification event id
-                * @param       {string}        initialValue    initial email type
-                * @returns     {Element}       dropdown menu object
-                */
-               _createDropdown: function(objectId, initialValue) {
-                       var dropdownMenu = elCreate('ul');
-                       dropdownMenu.className = 'dropdownMenu';
-                       elData(dropdownMenu, 'object-id', objectId);
                        
-                       var link, listItem, value, items = ['instant', 'daily', 'divider', 'none'];
-                       for (var i = 0; i < 4; i++) {
-                               value = items[i];
-                               
-                               listItem = elCreate('li');
+                       _dropDownMenu = elCreate('ul');
+                       _dropDownMenu.className = 'dropdownMenu';
+                       
+                       ['instant', 'daily', 'divider', 'none'].forEach((function (value) {
+                               var listItem = elCreate('li');
                                if (value === 'divider') {
                                        listItem.className = 'dropdownDivider';
                                }
                                else {
-                                       link = elCreate('a');
+                                       var link = elCreate('a');
+                                       link.href = '#';
                                        link.textContent = Language.get('wcf.user.notification.mailNotificationType.' + value);
                                        listItem.appendChild(link);
                                        elData(listItem, 'value', value);
-                                       listItem.addEventListener(WCF_CLICK_EVENT, _callbackSelectType);
-                                       
-                                       if (initialValue === value) {
-                                               listItem.className = 'active';
-                                       }
+                                       listItem.addEventListener(WCF_CLICK_EVENT, this._setEmailType.bind(this));
                                }
                                
-                               dropdownMenu.appendChild(listItem);
-                       }
+                               _dropDownMenu.appendChild(listItem);
+                       }).bind(this));
                        
-                       return dropdownMenu;
+                       UiReusableDropdown.init('UiNotificationSettingsEmailType', _dropDownMenu);
+               },
+               
+               _setCurrentEmailType: function (currentValue) {
+                       elBySelAll('li', _dropDownMenu, function (button) {
+                               var value = elData(button, 'value');
+                               button.classList[(value === currentValue) ? 'add' : 'remove']('active');
+                       });
+               },
+               
+               _showDropDown: function (referenceElement) {
+                       UiReusableDropdown.toggleDropdown('UiNotificationSettingsEmailType', referenceElement);
                },
                
                /**
-                * Sets the selected email notification type.
-                * 
-                * @param       {Object}        event           event object
+                * @param       {Event} event           event object
                 */
-               _selectType: function(event) {
+               _setEmailType: function (event) {
+                       event.preventDefault();
+                       
                        var value = elData(event.currentTarget, 'value');
-                       var groupId = ~~elData(event.currentTarget.parentNode, 'object-id');
                        
-                       var data = _data.get(groupId);
-                       data.mailValue.value = value;
-                       elBySel('span.title', data.mailSetting).textContent = Language.get('wcf.user.notification.mailNotificationType.' + value);
+                       this._getEmailTypeInputElement().value = value;
+                       
+                       var button = elBySel('.notificationSettingsEmailType[data-object-id="' + _objectId + '"]');
+                       elAttr(
+                               button,
+                               'aria-label',
+                               Language.get('wcf.user.notification.mailNotificationType.' + value)
+                       );
                        
-                       data.button.classList[(value === 'none') ? 'remove' : 'add']('yellow');
-                       data.button.classList[(value === 'none') ? 'remove' : 'add']('active');
+                       var icon = elBySel('.jsIconNotificationSettingsEmailType', button);
+                       icon.classList.remove('fa-clock-o');
+                       icon.classList.remove('fa-flash');
+                       icon.classList.remove('fa-times');
+                       icon.classList.remove('green');
+                       icon.classList.remove('red');
+                       
+                       switch (value) {
+                               case 'daily':
+                                       icon.classList.add('fa-clock-o');
+                                       icon.classList.add('green');
+                                       break;
+                               
+                               case 'instant':
+                                       icon.classList.add('fa-flash');
+                                       icon.classList.add('green');
+                                       break;
+                               
+                               case 'none':
+                                       icon.classList.add('fa-times');
+                                       icon.classList.add('red');
+                                       break;
+                       }
+                       
+                       _objectId = null;
+               },
+               
+               /**
+                * @return {HTMLInputElement}
+                */
+               _getEmailTypeInputElement: function () {
+                       return elById('settings_' + _objectId + '_mailNotificationType');
                }
        };
-       
-       return ControllerUserNotificationSettings;
 });
diff --git a/wcfsetup/install/files/style/ui/notification.scss b/wcfsetup/install/files/style/ui/notification.scss
new file mode 100644 (file)
index 0000000..e4060a9
--- /dev/null
@@ -0,0 +1,76 @@
+.notificationSettings {
+       margin-top: 30px;
+}
+
+.notificationSettingsCategory,
+.notificationSettingsItem {
+       display: flex;
+}
+
+.notificationSettingsCategory {
+       border-bottom: 2px solid currentColor;
+       color: $wcfTabularBoxHeadline;
+       font-weight: 600;
+       padding: 5px 0;
+}
+
+.notificationSettingsItem {
+       align-items: center;
+       padding: 5px 0;
+}
+
+.notificationSettingsItem:not(:last-child) {
+       border-bottom: 1px solid $wcfContentBorderInner;
+}
+
+.notificationSettingsEvent {
+       flex: 1 auto;
+       
+       > label {
+               cursor: pointer;
+       }
+}
+
+.notificationSettingsState {
+       align-items: center;
+       display: flex;
+       flex: 0 0 34px;
+       justify-content: center;
+       
+       @include screen-sm-up {
+               margin: 0 20px;
+       }
+       
+       @include screen-xs {
+               margin: 0 10px;
+       }
+       
+       input[type="checkbox"] {
+               opacity: 0;
+               position: absolute;
+               z-index: -1;
+               
+               &.focus-visible:focus ~ .icon {
+                       transform: scale(1.2);
+               }
+               
+               &:not(:checked) + .fa-bell {
+                       display: none;
+               }
+               
+               &:checked ~ .fa-bell-slash {
+                       display: none;
+               }
+       }
+}
+
+.notificationSettingsEmail {
+       align-items: center;
+       display: flex;
+       flex: 0 0 45px;
+       justify-content: flex-end;
+}
+.notificationSettingsEmailType {
+       align-items: center;
+       display: flex;
+}