diff --git a/data/interfaces/default/css/plexpy.css b/data/interfaces/default/css/plexpy.css index 066f9a37..3ff90a72 100644 --- a/data/interfaces/default/css/plexpy.css +++ b/data/interfaces/default/css/plexpy.css @@ -131,19 +131,19 @@ select.form-control:focus, .react-selectize.root-node.open .react-selectize-control .react-selectize-toggle-button path { fill: #999 !important; } -.selectize-control .selectize-input > div .email { +.selectize-control .selectize-input > div .item-value { opacity: 0.8; font-size: 12px; } -.selectize-control .selectize-input > div .user + .email { +.selectize-control .selectize-input > div .item-text + .item-value { margin-left: 5px; } -.selectize-control .selectize-input > div .email:before { +.selectize-control .selectize-input > div .item-value:before { content: '<'; opacity: 0.8; font-size: 12px; } -.selectize-control .selectize-input > div .email:after { +.selectize-control .selectize-input > div .item-value:after { content: '>'; opacity: 0.8; font-size: 12px; @@ -153,6 +153,25 @@ select.form-control:focus, display: block; color: #a0a0a0; } +.selectize-control .selectize-dropdown .select-all, +.selectize-control .selectize-dropdown .remove-all { + font-weight: bold; +} +.selectize-control .selectize-dropdown .border-all { + pointer-events: none; + display: block; + height: 1px; + margin: 9px -12px 9px -12px; + padding: 0 !important; + overflow: hidden; + background-color: #e5e5e5; +} +.selectize-control .selectize-dropdown .border-all:last-child { + display: none; +} +.selectize-dropdown .optgroup-header { + font-weight: bold; +} select.form-control option { color: #555; background-color: #fff; diff --git a/data/interfaces/default/notifier_config.html b/data/interfaces/default/notifier_config.html index 53128205..4c5bd81b 100644 --- a/data/interfaces/default/notifier_config.html +++ b/data/interfaces/default/notifier_config.html @@ -98,6 +98,33 @@

${item['description'] | n}

+ % elif item['input_type'] == 'selectize': +
+ +
+
+ +
+
+

${item['description'] | n}

+
% endif % endfor @@ -477,26 +504,37 @@ plugins: ['remove_button'], persist: false, maxItems: null, - valueField: 'email', - labelField: 'user', - searchField: ['user', 'email'], - options: ${json.dumps(user_emails) | n}, render: { item: function(item, escape) { return '
' + - (item.user ? '' + escape(item.user) + '' : '') + - (item.email ? '' + escape(item.email) + '' : '') + + (item.text ? '' + escape(item.text) + '' : '') + + (item.value ? '' + escape(item.value) + '' : '') + '
'; }, option: function(item, escape) { - var label = item.user || item.email; - var caption = item.user ? item.email : null; + var label = item.text || item.value; + var caption = item.text ? item.value : null; + if (item.value.endsWith('-all')) { + return '
' + escape(label) + '
' + } return '
' + escape(label) + (caption ? '' + escape(caption) + '' : '') + '
'; } }, + onItemAdd: function(value) { + if (value === 'select-all') { + var all_keys = $.map(this.options, function(option){ + return option.value.endsWith('-all') ? null : option.value; + }); + this.setValue(all_keys); + } else if (value === 'remove-all') { + this.clear(); + this.refreshOptions(); + this.positionDropdown(); + } + }, createFilter: function(input) { var match, regex; @@ -514,16 +552,15 @@ }, create: function(input) { if ((new RegExp('^' + REGEX_EMAIL + '$', 'i')).test(input)) { - return {email: input}; + return {value: input}; } var match = input.match(new RegExp('^([^<]*)\<' + REGEX_EMAIL + '\>$', 'i')); if (match) { return { - email : match[2], - user : $.trim(match[1]) + value : match[2], + text : $.trim(match[1]) }; } - alert('Invalid email address.'); return false; } }); diff --git a/plexpy/notifiers.py b/plexpy/notifiers.py index 657e7f18..15e0f278 100644 --- a/plexpy/notifiers.py +++ b/plexpy/notifiers.py @@ -1293,8 +1293,28 @@ class EMAIL(Notifier): logger.error(u"Tautulli Notifiers :: {name} notification failed: {e}".format(name=self.NAME, e=e)) return False + def get_user_emails(self): + emails = {u['email']: u['friendly_name'] for u in users.Users().get_users() if u['email']} + + user_emails_to = {v: '' for v in self.config['to']} + user_emails_cc = {v: '' for v in self.config['cc']} + user_emails_bcc = {v: '' for v in self.config['bcc']} + + user_emails_to.update(emails) + user_emails_cc.update(emails) + user_emails_bcc.update(emails) + + user_emails_to = [{'value': k, 'text': v} + for k, v in sorted(user_emails_to.iteritems(), key=lambda x: x[1].lower())] + user_emails_cc = [{'value': k, 'text': v} + for k, v in sorted(user_emails_cc.iteritems(), key=lambda x: x[1].lower())] + user_emails_bcc = [{'value': k, 'text': v} + for k, v in sorted(user_emails_bcc.iteritems(), key=lambda x: x[1].lower())] + + return user_emails_to, user_emails_cc, user_emails_bcc + def return_config_options(self): - user_emails = {} # User selection set with selectize options + user_emails_to, user_emails_cc, user_emails_bcc = self.get_user_emails() config_option = [{'label': 'From Name', 'value': self.config['from_name'], @@ -1312,22 +1332,22 @@ class EMAIL(Notifier): 'value': self.config['to'], 'name': 'email_to', 'description': 'The email address(es) of the recipients.', - 'input_type': 'select', - 'select_options': user_emails + 'input_type': 'selectize', + 'select_options': user_emails_to }, {'label': 'CC', 'value': self.config['cc'], 'name': 'email_cc', 'description': 'The email address(es) to CC.', - 'input_type': 'select', - 'select_options': user_emails + 'input_type': 'selectize', + 'select_options': user_emails_cc }, {'label': 'BCC', 'value': self.config['bcc'], 'name': 'email_bcc', 'description': 'The email address(es) to BCC.', - 'input_type': 'select', - 'select_options': user_emails + 'input_type': 'selectize', + 'select_options': user_emails_bcc }, {'label': 'SMTP Server', 'value': self.config['smtp_server'], diff --git a/plexpy/users.py b/plexpy/users.py index 6bbab6b7..08b9f254 100644 --- a/plexpy/users.py +++ b/plexpy/users.py @@ -597,7 +597,7 @@ class Users(object): for item in result: user = {'user_id': item['user_id'], 'username': item['username'], - 'friendly_name': item['friendly_name'], + 'friendly_name': item['friendly_name'] or item['username'], 'email': item['email'] } users.append(user)