mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-14 01:02:59 -07:00
Add selectize input for email for newsletters
This commit is contained in:
parent
5ac5b3cd29
commit
a13d93f239
2 changed files with 94 additions and 26 deletions
|
@ -1,10 +1,14 @@
|
||||||
% if newsletter:
|
% if newsletter:
|
||||||
<%!
|
<%!
|
||||||
from plexpy import helpers, notifiers
|
import json
|
||||||
|
from plexpy import helpers, notifiers, users
|
||||||
|
|
||||||
email_notifiers = [n for n in notifiers.get_notifiers() if n['agent_name'] == 'email']
|
email_notifiers = [n for n in notifiers.get_notifiers() if n['agent_name'] == 'email']
|
||||||
sorted(email_notifiers, key=lambda k: (k['agent_label'], k['friendly_name'], k['id']))
|
sorted(email_notifiers, key=lambda k: (k['agent_label'], k['friendly_name'], k['id']))
|
||||||
email_notifiers = [{'id': 0, 'agent_label': 'New Email Configuration', 'friendly_name': ''}] + email_notifiers
|
email_notifiers = [{'id': 0, 'agent_label': 'New Email Configuration', 'friendly_name': ''}] + email_notifiers
|
||||||
|
|
||||||
|
user_emails = [{'user': u['friendly_name'] or u['username'], 'email': u['email']} for u in users.Users().get_users() if u['email']]
|
||||||
|
sorted(user_emails, key=lambda u: u['user'])
|
||||||
%>
|
%>
|
||||||
<div class="modal-dialog" role="document">
|
<div class="modal-dialog" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
|
@ -56,7 +60,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="${item['name']}">${item['label']}</label>
|
<label for="${item['name']}">${item['label']}</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-12">
|
||||||
<input type="${item['input_type']}" class="form-control" id="${item['name']}" name="${item['name']}" value="${item['value']}" size="30" ${'readonly' if item.get('readonly') else ''}>
|
<input type="${item['input_type']}" class="form-control" id="${item['name']}" name="${item['name']}" value="${item['value']}" size="30" ${'readonly' if item.get('readonly') else ''}>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -76,7 +80,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="${item['name']}">${item['label']}</label>
|
<label for="${item['name']}">${item['label']}</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-12">
|
||||||
<input type="button" class="btn btn-bright" id="${item['name']}" name="${item['name']}" value="${item['value']}">
|
<input type="button" class="btn btn-bright" id="${item['name']}" name="${item['name']}" value="${item['value']}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -94,7 +98,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="${item['name']}">${item['label']}</label>
|
<label for="${item['name']}">${item['label']}</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-12">
|
||||||
<select class="form-control" id="${item['name']}" name="${item['name']}">
|
<select class="form-control" id="${item['name']}" name="${item['name']}">
|
||||||
% for key, value in sorted(item['select_options'].iteritems()):
|
% for key, value in sorted(item['select_options'].iteritems()):
|
||||||
% if key == item['value']:
|
% if key == item['value']:
|
||||||
|
@ -115,7 +119,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="friendly_name">Description</label>
|
<label for="friendly_name">Description</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-12">
|
||||||
<input type="text" class="form-control" id="friendly_name" name="friendly_name" value="${newsletter['friendly_name']}" size="30">
|
<input type="text" class="form-control" id="friendly_name" name="friendly_name" value="${newsletter['friendly_name']}" size="30">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -130,7 +134,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="email_notifier">Email Notification Agent</label>
|
<label for="email_notifier">Email Notification Agent</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-12">
|
||||||
<select class="form-control" id="email_notifier" name="email_notifier">
|
<select class="form-control" id="email_notifier" name="email_notifier">
|
||||||
% for notifier in email_notifiers:
|
% for notifier in email_notifiers:
|
||||||
<% selected = 'selected' if notifier['id'] == newsletter['email_config']['notifier'] else '' %>
|
<% selected = 'selected' if notifier['id'] == newsletter['email_config']['notifier'] else '' %>
|
||||||
|
@ -145,19 +149,19 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">Use an exisiting Email notification agent or enter a new configuration below.</p>
|
<p class="help-block">Use an existing Email notification agent or enter a new configuration below.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="email_subject">Email Subject</label>
|
<label for="email_subject">Email Subject</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-12">
|
||||||
<input type="text" class="form-control" id="email_subject" name="email_subject" value="${newsletter['email_config']['subject']}" size="30">
|
<input type="text" class="form-control" id="email_subject" name="email_subject" value="${newsletter['email_config']['subject']}" size="30">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">
|
<p class="help-block">
|
||||||
Optional: Enter a subject line for the email. Leave blank for default.
|
Optional: Enter a subject line for the email. Leave blank for default.
|
||||||
<br>
|
<br>
|
||||||
Note: You may include <span class="inline-pre">{start_date}</span> and <span class="inline-pre">{end_date}</span> as parameters. The global date format under Settings > General will be used.
|
Note: You may include <span class="inline-pre">{server_name}</span>, <span class="inline-pre">{start_date}</span>, and <span class="inline-pre">{end_date}</span> as parameters. The global date format under Settings > General will be used.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -172,7 +176,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="${item['name']}">${item['label']}</label>
|
<label for="${item['name']}">${item['label']}</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-12">
|
||||||
<input type="${item['input_type']}" class="form-control" id="${item['name']}" name="${item['name']}" value="${item['value']}" size="30" ${'readonly' if item.get('readonly') else ''}>
|
<input type="${item['input_type']}" class="form-control" id="${item['name']}" name="${item['name']}" value="${item['value']}" size="30" ${'readonly' if item.get('readonly') else ''}>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -192,7 +196,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="${item['name']}">${item['label']}</label>
|
<label for="${item['name']}">${item['label']}</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-12">
|
||||||
<input type="button" class="btn btn-bright" id="${item['name']}" name="${item['name']}" value="${item['value']}">
|
<input type="button" class="btn btn-bright" id="${item['name']}" name="${item['name']}" value="${item['value']}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -210,7 +214,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="${item['name']}">${item['label']}</label>
|
<label for="${item['name']}">${item['label']}</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-12">
|
||||||
<select class="form-control" id="${item['name']}" name="${item['name']}">
|
<select class="form-control" id="${item['name']}" name="${item['name']}">
|
||||||
% for key, value in sorted(item['select_options'].iteritems()):
|
% for key, value in sorted(item['select_options'].iteritems()):
|
||||||
% if key == item['value']:
|
% if key == item['value']:
|
||||||
|
@ -237,7 +241,7 @@
|
||||||
</p>
|
</p>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-12">
|
||||||
<input type="button" class="btn btn-bright" id="preview_newsletter" name="preview_newsletter" value="Preview ${newsletter['agent_label']} Newsletter">
|
<input type="button" class="btn btn-bright" id="preview_newsletter" name="preview_newsletter" value="Preview ${newsletter['agent_label']} Newsletter">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -248,7 +252,7 @@
|
||||||
</p>
|
</p>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-12">
|
||||||
<input type="button" class="btn btn-bright" id="test_newsletter" name="test_newsletter" value="Test ${newsletter['agent_label']} Newsletter">
|
<input type="button" class="btn btn-bright" id="test_newsletter" name="test_newsletter" value="Test ${newsletter['agent_label']} Newsletter">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -284,7 +288,7 @@
|
||||||
maxItems: null
|
maxItems: null
|
||||||
});
|
});
|
||||||
var incl_libraries = $incl_libraries[0].selectize;
|
var incl_libraries = $incl_libraries[0].selectize;
|
||||||
incl_libraries.setValue(${next((c['value'] for c in newsletter['config_options'] if c['name'] == 'recently_added_incl_libraries'), []) | n});
|
incl_libraries.setValue(${json.dumps(next((c['value'] for c in newsletter['config_options'] if c['name'] == 'recently_added_incl_libraries'), [])) | n});
|
||||||
|
|
||||||
$('#email_notifier').change(function () {
|
$('#email_notifier').change(function () {
|
||||||
if ($(this).val() === "0") {
|
if ($(this).val() === "0") {
|
||||||
|
@ -294,6 +298,69 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var REGEX_EMAIL = '([a-z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+/=?^_`{|}~-]+)*@' +
|
||||||
|
'(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)';
|
||||||
|
var $email_selectors = $('#email_to, #email_cc, #email_bcc').selectize({
|
||||||
|
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 '<div>' +
|
||||||
|
(item.user ? '<span class="user">' + escape(item.user) + '</span>' : '') +
|
||||||
|
(item.email ? '<span class="email">' + escape(item.email) + '</span>' : '') +
|
||||||
|
'</div>';
|
||||||
|
},
|
||||||
|
option: function(item, escape) {
|
||||||
|
var label = item.user || item.email;
|
||||||
|
var caption = item.user ? item.email : null;
|
||||||
|
return '<div>' +
|
||||||
|
escape(label) +
|
||||||
|
(caption ? '<span class="caption">' + escape(caption) + '</span>' : '') +
|
||||||
|
'</div>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
createFilter: function(input) {
|
||||||
|
var match, regex;
|
||||||
|
|
||||||
|
// email@address.com
|
||||||
|
regex = new RegExp('^' + REGEX_EMAIL + '$', 'i');
|
||||||
|
match = input.match(regex);
|
||||||
|
if (match) return !this.options.hasOwnProperty(match[0]);
|
||||||
|
|
||||||
|
// user <email@address.com>
|
||||||
|
regex = new RegExp('^([^<]*)\<' + REGEX_EMAIL + '\>$', 'i');
|
||||||
|
match = input.match(regex);
|
||||||
|
if (match) return !this.options.hasOwnProperty(match[2]);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
create: function(input) {
|
||||||
|
if ((new RegExp('^' + REGEX_EMAIL + '$', 'i')).test(input)) {
|
||||||
|
return {email: input};
|
||||||
|
}
|
||||||
|
var match = input.match(new RegExp('^([^<]*)\<' + REGEX_EMAIL + '\>$', 'i'));
|
||||||
|
if (match) {
|
||||||
|
return {
|
||||||
|
email : match[2],
|
||||||
|
user : $.trim(match[1])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
alert('Invalid email address.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var email_to = $email_selectors[0].selectize;
|
||||||
|
var email_cc = $email_selectors[1].selectize;
|
||||||
|
var email_bcc = $email_selectors[2].selectize;
|
||||||
|
email_to.setValue(${json.dumps(next((c['value'] for c in newsletter['email_config_options'] if c['name'] == 'email_to'), [])) | n});
|
||||||
|
email_cc.setValue(${json.dumps(next((c['value'] for c in newsletter['email_config_options'] if c['name'] == 'email_cc'), [])) | n});
|
||||||
|
email_bcc.setValue(${json.dumps(next((c['value'] for c in newsletter['email_config_options'] if c['name'] == 'email_bcc'), [])) | n});
|
||||||
|
|
||||||
function reloadModal() {
|
function reloadModal() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'get_newsletter_config_modal',
|
url: 'get_newsletter_config_modal',
|
||||||
|
|
|
@ -238,17 +238,18 @@ def serve_template(templatename, **kwargs):
|
||||||
class Newsletter(object):
|
class Newsletter(object):
|
||||||
NAME = ''
|
NAME = ''
|
||||||
_DEFAULT_CONFIG = {}
|
_DEFAULT_CONFIG = {}
|
||||||
|
_DEFAULT_EMAIL_CONFIG = EMAIL().return_default_config()
|
||||||
|
_DEFAULT_EMAIL_CONFIG['from_name'] = 'Tautulli Newsletter'
|
||||||
|
_DEFAULT_EMAIL_CONFIG['notifier'] = 0
|
||||||
|
_DEFAULT_EMAIL_CONFIG['subject'] = 'Tautulli Newsletter'
|
||||||
|
_TEMPLATE = ''
|
||||||
|
|
||||||
def __init__(self, config=None, email_config=None):
|
def __init__(self, config=None, email_config=None):
|
||||||
self._default_email_config = EMAIL().return_default_config()
|
|
||||||
self._default_email_config['from_name'] = 'Tautulli Newsletter'
|
|
||||||
self._default_email_config['notifier'] = 0
|
|
||||||
self._default_email_config['subject'] = 'Tautulli Newsletter'
|
|
||||||
|
|
||||||
self.config = self.set_config(config=config, default=self._DEFAULT_CONFIG)
|
self.config = self.set_config(config=config, default=self._DEFAULT_CONFIG)
|
||||||
self.email_config = self.set_config(config=email_config, default=self._default_email_config)
|
self.email_config = self.set_config(config=email_config, default=self._DEFAULT_EMAIL_CONFIG)
|
||||||
|
|
||||||
self.parameters = {}
|
self.parameters = {'server_name': plexpy.CONFIG.PMS_NAME}
|
||||||
|
self.is_preview = False
|
||||||
|
|
||||||
def set_config(self, config=None, default=None):
|
def set_config(self, config=None, default=None):
|
||||||
return self._validate_config(config=config, default=default)
|
return self._validate_config(config=config, default=default)
|
||||||
|
@ -346,7 +347,7 @@ class RecentlyAdded(Newsletter):
|
||||||
elif not isinstance(self.config['incl_libraries'], list):
|
elif not isinstance(self.config['incl_libraries'], list):
|
||||||
self.config['incl_libraries'] = [self.config['incl_libraries']]
|
self.config['incl_libraries'] = [self.config['incl_libraries']]
|
||||||
|
|
||||||
self._default_email_config['subject'] = 'Recently Added to Plex! ({end_date})'
|
self._DEFAULT_EMAIL_CONFIG['subject'] = 'Recently Added to Plex! ({end_date})'
|
||||||
|
|
||||||
date_format = helpers.momentjs_to_arrow(plexpy.CONFIG.DATE_FORMAT)
|
date_format = helpers.momentjs_to_arrow(plexpy.CONFIG.DATE_FORMAT)
|
||||||
|
|
||||||
|
@ -355,8 +356,8 @@ class RecentlyAdded(Newsletter):
|
||||||
self.end_date = arrow.get(self.end_time).format(date_format)
|
self.end_date = arrow.get(self.end_time).format(date_format)
|
||||||
self.start_date = arrow.get(self.start_time).format(date_format)
|
self.start_date = arrow.get(self.start_time).format(date_format)
|
||||||
|
|
||||||
self.parameters = {'start_date': self.start_date,
|
self.parameters['start_date'] = self.start_date
|
||||||
'end_date': self.end_date}
|
self.parameters['end_date'] = self.end_date
|
||||||
|
|
||||||
self.plexpy_config = {
|
self.plexpy_config = {
|
||||||
'pms_identifier': plexpy.CONFIG.PMS_IDENTIFIER,
|
'pms_identifier': plexpy.CONFIG.PMS_IDENTIFIER,
|
||||||
|
@ -515,7 +516,7 @@ class RecentlyAdded(Newsletter):
|
||||||
'input_type': 'number'
|
'input_type': 'number'
|
||||||
},
|
},
|
||||||
{'label': 'Included Libraries',
|
{'label': 'Included Libraries',
|
||||||
'value': json.dumps(self.config['incl_libraries']),
|
'value': self.config['incl_libraries'],
|
||||||
'description': 'Select the libraries to include in the newsletter.',
|
'description': 'Select the libraries to include in the newsletter.',
|
||||||
'name': 'recently_added_incl_libraries',
|
'name': 'recently_added_incl_libraries',
|
||||||
'input_type': 'select',
|
'input_type': 'select',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue