mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-12 08:16:06 -07:00
Add server selection dropdown to settings
This commit is contained in:
parent
e1dca1509a
commit
2621da7d36
7 changed files with 305 additions and 228 deletions
|
@ -60,7 +60,8 @@ select[multiple] option {
|
||||||
-moz-border-radius: 2px;
|
-moz-border-radius: 2px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
select.form-control {
|
select.form-control,
|
||||||
|
div.form-control .selectize-input {
|
||||||
margin: 5px 0 5px 0;
|
margin: 5px 0 5px 0;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border: 0px solid #444;
|
border: 0px solid #444;
|
||||||
|
@ -80,14 +81,36 @@ select.form-control {
|
||||||
transition: background-color .3s;
|
transition: background-color .3s;
|
||||||
}
|
}
|
||||||
.selectize-control.form-control .selectize-input {
|
.selectize-control.form-control .selectize-input {
|
||||||
display: flex;
|
display: flex !important;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
.selectize-control.form-control.wizard-pms-ip .selectize-input {
|
.selectize-control.form-control.selectize-pms-ip .selectize-input {
|
||||||
padding: 6px 12px !important;
|
padding-left: 12px !important;
|
||||||
|
border-top-left-radius: 3px;
|
||||||
|
border-bottom-left-radius: 3px;
|
||||||
|
min-height: 32px !important;
|
||||||
|
}
|
||||||
|
.input-group .selectize-control.form-control.selectize-pms-ip .selectize-input > div {
|
||||||
|
max-width: 450px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.wizard-input-section .selectize-control.form-control.selectize-pms-ip .selectize-input > div {
|
||||||
|
max-width: 360px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.selectize-dropdown.form-control.selectize-pms-ip {
|
||||||
|
margin-top: -4px;
|
||||||
|
}
|
||||||
|
.wizard-input-section .selectize-control.form-control.selectize-pms-ip .selectize-dropdown .selectize-dropdown-content {
|
||||||
|
max-height: 150px;
|
||||||
|
}
|
||||||
|
.wizard-input-section .selectize-dropdown.form-control.selectize-pms-ip {
|
||||||
|
margin-top: 0 !important;
|
||||||
}
|
}
|
||||||
.react-selectize.root-node .react-selectize-control .react-selectize-placeholder {
|
.react-selectize.root-node .react-selectize-control .react-selectize-placeholder {
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
|
@ -137,33 +160,38 @@ select.form-control:focus,
|
||||||
.react-selectize.root-node.open .react-selectize-control .react-selectize-toggle-button path {
|
.react-selectize.root-node.open .react-selectize-control .react-selectize-toggle-button path {
|
||||||
fill: #999 !important;
|
fill: #999 !important;
|
||||||
}
|
}
|
||||||
.selectize-control .selectize-input > div .item-value {
|
.selectize-input > div .item-text {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.selectize-input > div .item-value {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.selectize-control .selectize-input > div .item-text + .item-value {
|
.selectize-input > div .item-text + .item-value {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
.selectize-control .selectize-input > div .item-value:before {
|
.selectize-input > div .item-value:before {
|
||||||
content: '<';
|
content: '<';
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
.selectize-control .selectize-input > div .item-value:after {
|
.selectize-input > div .item-value:after {
|
||||||
content: '>';
|
content: '>';
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
.selectize-control .selectize-dropdown .caption {
|
.selectize-dropdown .caption {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
display: block;
|
display: block;
|
||||||
color: #a0a0a0;
|
color: #a0a0a0;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.selectize-control .selectize-dropdown .select-all,
|
.selectize-dropdown .select-all,
|
||||||
.selectize-control .selectize-dropdown .remove-all {
|
.selectize-dropdown .remove-all {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.selectize-control .selectize-dropdown .border-all {
|
.selectize-dropdown .border-all {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
display: block;
|
display: block;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
|
@ -172,7 +200,7 @@ select.form-control:focus,
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: #e5e5e5;
|
background-color: #e5e5e5;
|
||||||
}
|
}
|
||||||
.selectize-control .selectize-dropdown .border-all:last-child {
|
.selectize-dropdown .border-all:last-child {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.selectize-dropdown .optgroup-header {
|
.selectize-dropdown .optgroup-header {
|
||||||
|
@ -622,18 +650,8 @@ textarea.form-control:focus {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
.form-control-feedback {
|
.form-control-feedback {
|
||||||
position: absolute;
|
|
||||||
color: #F9AA03;
|
color: #F9AA03;
|
||||||
top: 0;
|
margin: 5px 40px 5px 0;
|
||||||
right: 0;
|
|
||||||
margin: 5px 10px 5px 0;
|
|
||||||
z-index: 2;
|
|
||||||
display: block;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
line-height: 32px;
|
|
||||||
text-align: center;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
}
|
||||||
.form-control[readonly] {
|
.form-control[readonly] {
|
||||||
background-color: #555;
|
background-color: #555;
|
||||||
|
|
|
@ -518,7 +518,6 @@
|
||||||
'(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[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({
|
var $email_selectors = $('#email_to, #email_cc, #email_bcc').selectize({
|
||||||
plugins: ['remove_button'],
|
plugins: ['remove_button'],
|
||||||
persist: false,
|
|
||||||
maxItems: null,
|
maxItems: null,
|
||||||
render: {
|
render: {
|
||||||
item: function(item, escape) {
|
item: function(item, escape) {
|
||||||
|
|
|
@ -623,9 +623,11 @@
|
||||||
<div class="form-group has-feedback" id="pms_ip_group">
|
<div class="form-group has-feedback" id="pms_ip_group">
|
||||||
<label for="pms_ip">Plex IP or Hostname</label>
|
<label for="pms_ip">Plex IP or Hostname</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" class="pms-settings form-control" id="pms_ip" name="pms_ip" value="${config['pms_ip']}" size="30" data-parsley-trigger="change" aria-describedby="server-verified" data-parsley-errors-container="#pms_ip_error" required>
|
<select class="form-control pms-settings selectize-pms-ip" id="pms_ip" name="pms_ip" data-parsley-trigger="change" aria-describedby="server-verified" data-parsley-errors-container="#pms_ip_error" required>
|
||||||
|
<option value="${config['pms_ip']}" selected>${config['pms_ip']}</option>
|
||||||
|
</select>
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<button class="btn btn-form" type="button" id="verify_server_button">Verify Server</button>
|
<button class="btn btn-form" type="button" id="verify_server_button">Verify Server</button>
|
||||||
</span>
|
</span>
|
||||||
|
@ -634,7 +636,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="pms_ip_error" class="alert alert-danger settings-alert" role="alert"></div>
|
<div id="pms_ip_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">IP Address or hostname for Plex Media Server.</p>
|
<p class="help-block">Select your Plex Media Server from the dropdown menu or enter an IP address or hostname.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="pms_port">Plex Port</label>
|
<label for="pms_port">Plex Port</label>
|
||||||
|
@ -659,16 +661,10 @@
|
||||||
<p class="help-block">If you have secure connections enabled on your Plex Server, communicate with it securely.</p>
|
<p class="help-block">If you have secure connections enabled on your Plex Server, communicate with it securely.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="checkbox advanced-setting">
|
<div class="checkbox advanced-setting">
|
||||||
% if config['pms_is_cloud']:
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" id="pms_url_manual" name="pms_url_manual" value="1" disabled> Manual Connection
|
|
||||||
</label>
|
|
||||||
<span style="color: #eb8600; padding-left: 10px;"> Not available for Plex Cloud servers.</span>
|
|
||||||
% else:
|
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="pms_url_manual" name="pms_url_manual" value="1" ${config['pms_url_manual']}> Manual Connection
|
<input type="checkbox" id="pms_url_manual" name="pms_url_manual" value="1" ${config['pms_url_manual']}> Manual Connection
|
||||||
</label>
|
</label>
|
||||||
% endif
|
<span id="cloudManualConnection" style="display: none; color: #eb8600; padding-left: 10px;"> Not available for Plex Cloud servers.</span>
|
||||||
<p class="help-block">Use the user defined connection details. Do not retrieve the server connection URL automatically.</p>
|
<p class="help-block">Use the user defined connection details. Do not retrieve the server connection URL automatically.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group advanced-setting">
|
<div class="form-group advanced-setting">
|
||||||
|
@ -689,6 +685,7 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<input type="hidden" id="pms_is_cloud" name="pms_is_cloud" value="${config['pms_is_cloud']}">
|
||||||
<input type="hidden" id="pms_identifier" name="pms_identifier" value="${config['pms_identifier']}">
|
<input type="hidden" id="pms_identifier" name="pms_identifier" value="${config['pms_identifier']}">
|
||||||
<input type="checkbox" name="server_changed" id="server_changed" value="1" style="display: none;">
|
<input type="checkbox" name="server_changed" id="server_changed" value="1" style="display: none;">
|
||||||
|
|
||||||
|
@ -721,16 +718,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
% if config['pms_is_cloud']:
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" id="monitor_pms_updates" name="monitor_pms_updates" value="1" disabled> Monitor Plex Updates
|
|
||||||
</label>
|
|
||||||
<span style="color: #eb8600; padding-left: 10px;"> Not available for Plex Cloud servers.</span>
|
|
||||||
% else:
|
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="monitor_pms_updates" name="monitor_pms_updates" value="1" ${config['monitor_pms_updates']}> Monitor Plex Updates
|
<input type="checkbox" id="monitor_pms_updates" name="monitor_pms_updates" value="1" ${config['monitor_pms_updates']}> Monitor Plex Updates
|
||||||
</label>
|
</label>
|
||||||
% endif
|
<span id="cloudMonitorUpdates" style="display: none; color: #eb8600; padding-left: 10px;"> Not available for Plex Cloud servers.</span>
|
||||||
<p class="help-block">Enable to have Tautulli check if updates are available for the Plex Media Server.</p>
|
<p class="help-block">Enable to have Tautulli check if updates are available for the Plex Media Server.</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="pms_update_options">
|
<div id="pms_update_options">
|
||||||
|
@ -753,17 +744,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
% if config['pms_is_cloud']:
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" id="monitor_remote_access" name="monitor_remote_access" value="1" disabled> Monitor Plex Remote Access
|
|
||||||
</label>
|
|
||||||
<span style="color: #eb8600; padding-left: 10px;"> Not available for Plex Cloud servers.</span>
|
|
||||||
% else:
|
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="monitor_remote_access" name="monitor_remote_access" value="1" ${config['monitor_remote_access']}> Monitor Plex Remote Access
|
<input type="checkbox" id="monitor_remote_access" name="monitor_remote_access" value="1" ${config['monitor_remote_access']}> Monitor Plex Remote Access
|
||||||
</label>
|
</label>
|
||||||
|
<span id="cloudMonitorRemoteAccess" style="display: none; color: #eb8600; padding-left: 10px;"> Not available for Plex Cloud servers.</span>
|
||||||
<span id="remoteAccessCheck" style="color: #eb8600; padding-left: 10px;"></span>
|
<span id="remoteAccessCheck" style="color: #eb8600; padding-left: 10px;"></span>
|
||||||
% endif
|
|
||||||
<p class="help-block">Enable to have Tautulli check if remote access to the Plex Media Server goes down.</p>
|
<p class="help-block">Enable to have Tautulli check if remote access to the Plex Media Server goes down.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1787,6 +1772,117 @@ $(document).ready(function() {
|
||||||
verifyServer();
|
verifyServer();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var $select_pms = $('#pms_ip').selectize({
|
||||||
|
createOnBlur: true,
|
||||||
|
openOnFocus: true,
|
||||||
|
maxItems: 1,
|
||||||
|
closeAfterSelect: true,
|
||||||
|
sortField: 'label',
|
||||||
|
searchField: ['label', 'value'],
|
||||||
|
inputClass: 'form-control selectize-input',
|
||||||
|
dropdownParent: 'body',
|
||||||
|
render: {
|
||||||
|
item: function (item, escape) {
|
||||||
|
var label = item.label || item.value;
|
||||||
|
var caption = item.label ? item.value : null;
|
||||||
|
return '<div data-ssl="' + item.httpsRequired +
|
||||||
|
'" data-local="' + item.local +
|
||||||
|
'" data-identifier="' + item.clientIdentifier +
|
||||||
|
'" data-ip="' + item.ip +
|
||||||
|
'" data-port="' + item.port +
|
||||||
|
'" data-is_cloud="' + item.is_cloud +
|
||||||
|
'" data-label="' + item.label + '">' +
|
||||||
|
'<span class="item-text">' + escape(label) + '</span>' +
|
||||||
|
(caption ? '<span class="item-value">' + escape(caption) + '</span>' : '') +
|
||||||
|
'</div>';
|
||||||
|
},
|
||||||
|
option: function (item, escape) {
|
||||||
|
var label = item.label || item.value;
|
||||||
|
var caption = item.label ? item.value : null;
|
||||||
|
return '<div data-ssl="' + item.httpsRequired +
|
||||||
|
'" data-local="' + item.local +
|
||||||
|
'" data-identifier="' + item.clientIdentifier +
|
||||||
|
'" data-ip="' + item.ip +
|
||||||
|
'" data-port="' + item.port +
|
||||||
|
'" data-is_cloud="' + item.is_cloud +
|
||||||
|
'" data-label="' + item.label + '">' +
|
||||||
|
escape(label) +
|
||||||
|
(caption ? '<span class="caption">' + escape(caption) + '</span>' : '') +
|
||||||
|
'</div>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
create: function(input) {
|
||||||
|
return {label: '', value: input};
|
||||||
|
},
|
||||||
|
onChange: function (item) {
|
||||||
|
var pms_ip_selected = this.getItem(item)[0];
|
||||||
|
var identifier = $(pms_ip_selected).data('identifier');
|
||||||
|
var port = $(pms_ip_selected).data('port');
|
||||||
|
var local = $(pms_ip_selected).data('local');
|
||||||
|
var ssl = $(pms_ip_selected).data('ssl');
|
||||||
|
var is_cloud = $(pms_ip_selected).data('is_cloud');
|
||||||
|
|
||||||
|
$("#pms_identifier").val(identifier !== 'undefined' ? identifier : '');
|
||||||
|
$('#pms_port').val((port !== 'undefined' ? port : 32400));
|
||||||
|
$('#pms_is_remote').prop('checked', (local !== 'undefined' && local === 0));
|
||||||
|
$('#pms_ssl').prop('checked', (ssl !== 'undefined' && ssl === 1));
|
||||||
|
$('#pms_is_cloud').val((is_cloud !== 'undefined' && is_cloud === true ? 1 : 0));
|
||||||
|
$('#pms_url_manual').prop('checked', false);
|
||||||
|
PMSCloudCheck();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var select_pms = $select_pms[0].selectize;
|
||||||
|
|
||||||
|
function getServerOptions(token) {
|
||||||
|
$.ajax({
|
||||||
|
url: 'discover',
|
||||||
|
data: {
|
||||||
|
token: token
|
||||||
|
},
|
||||||
|
success: function (result) {
|
||||||
|
if (result) {
|
||||||
|
var existing_value = $('#pms_ip').val();
|
||||||
|
result.forEach(function (item) {
|
||||||
|
if (item.value === existing_value) {
|
||||||
|
select_pms.updateOption(item.value, item);
|
||||||
|
} else {
|
||||||
|
select_pms.addOption(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
getServerOptions();
|
||||||
|
|
||||||
|
function PMSCloudCheck () {
|
||||||
|
if ($('#pms_is_cloud').val() === "1") {
|
||||||
|
$('#pms_port').val(443).prop('readonly', true);
|
||||||
|
$('#pms_is_remote').prop('checked', true).prop('disabled', true);
|
||||||
|
$('#pms_ssl').prop('checked', true).prop('disabled', true);
|
||||||
|
$('#pms_url_manual').prop('checked', false).prop('disabled', true);
|
||||||
|
$('#monitor_pms_updates').prop('checked', false).prop('disabled', true);
|
||||||
|
$('#pms_update_options').hide();
|
||||||
|
$('#monitor_remote_access').prop('checked', false).prop('disabled', true);
|
||||||
|
$('#cloudManualConnection').show();
|
||||||
|
$('#cloudMonitorUpdates').show();
|
||||||
|
$('#cloudMonitorRemoteAccess').show();
|
||||||
|
$('#remoteAccessCheck').hide();
|
||||||
|
} else {
|
||||||
|
$('#pms_port').prop('readonly', false);
|
||||||
|
$('#pms_is_remote').prop('disabled', false);
|
||||||
|
$('#pms_ssl').prop('disabled', false);
|
||||||
|
$('#pms_url_manual').prop('disabled', false);
|
||||||
|
$('#monitor_pms_updates').prop('disabled', false);
|
||||||
|
$('#monitor_remote_access').prop('disabled', false);
|
||||||
|
$('#cloudManualConnection').hide();
|
||||||
|
$('#cloudMonitorUpdates').hide();
|
||||||
|
$('#cloudMonitorRemoteAccess').hide();
|
||||||
|
remoteAccessEnabledCheck();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PMSCloudCheck();
|
||||||
|
|
||||||
function verifyServer(_callback) {
|
function verifyServer(_callback) {
|
||||||
var pms_ip = $("#pms_ip").val();
|
var pms_ip = $("#pms_ip").val();
|
||||||
var pms_port = $("#pms_port").val();
|
var pms_port = $("#pms_port").val();
|
||||||
|
@ -1875,6 +1971,7 @@ $(document).ready(function() {
|
||||||
$("#pms-token-status").html('<i class="fa fa-check"></i> ' + msg);
|
$("#pms-token-status").html('<i class="fa fa-check"></i> ' + msg);
|
||||||
$("#pms_token").val(authToken);
|
$("#pms_token").val(authToken);
|
||||||
$('#pms-auth-modal').modal('hide');
|
$('#pms-auth-modal').modal('hide');
|
||||||
|
getServerOptions(authToken);
|
||||||
} else {
|
} else {
|
||||||
$("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i> ' + msg);
|
$("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i> ' + msg);
|
||||||
}
|
}
|
||||||
|
@ -1903,18 +2000,21 @@ $(document).ready(function() {
|
||||||
pms_logs_debug = false;
|
pms_logs_debug = false;
|
||||||
pms_logs = false;
|
pms_logs = false;
|
||||||
|
|
||||||
$.ajax({
|
function remoteAccessEnabledCheck() {
|
||||||
url: 'get_server_pref',
|
$.ajax({
|
||||||
data: { pref: 'PublishServerOnPlexOnlineKey' },
|
url: 'get_server_pref',
|
||||||
async: true,
|
data: { pref: 'PublishServerOnPlexOnlineKey' },
|
||||||
success: function(data) {
|
async: true,
|
||||||
if (data !== 'true') {
|
success: function(data) {
|
||||||
$("#remoteAccessCheck").html("Remote access must be enabled on your Plex Server. <a target='_blank' href='${anon_url('https://support.plex.tv/hc/en-us/articles/200484543-Enabling-Remote-Access-for-a-Server')}'>Click here</a> for help.");
|
if (data !== 'true') {
|
||||||
$("#monitor_remote_access").attr("disabled", true);
|
$("#remoteAccessCheck").html("Remote access must be enabled on your Plex Server. <a target='_blank' href='${anon_url('https://support.plex.tv/hc/en-us/articles/200484543-Enabling-Remote-Access-for-a-Server')}'>Click here</a> for help.");
|
||||||
$("#monitor_remote_access").attr("checked", false);
|
$("#monitor_remote_access").attr("disabled", true);
|
||||||
|
$("#monitor_remote_access").attr("checked", false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
|
remoteAccessEnabledCheck();
|
||||||
|
|
||||||
// Sortable home_sections
|
// Sortable home_sections
|
||||||
function set_home_sections() {
|
function set_home_sections() {
|
||||||
|
@ -1940,7 +2040,7 @@ $(document).ready(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
$('[id^=hsec-]').change(function() { set_home_sections(); });
|
$('[id^=hsec-]').change(function() { set_home_sections(); });
|
||||||
set_home_sections()
|
set_home_sections();
|
||||||
|
|
||||||
// Sortable home_stats_cards
|
// Sortable home_stats_cards
|
||||||
function set_home_stats_cards() {
|
function set_home_stats_cards() {
|
||||||
|
@ -1966,7 +2066,7 @@ $(document).ready(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
$('[id^=hscard-]').change(function() { set_home_stats_cards(); });
|
$('[id^=hscard-]').change(function() { set_home_stats_cards(); });
|
||||||
set_home_stats_cards()
|
set_home_stats_cards();
|
||||||
|
|
||||||
// Sortable home_library_cards
|
// Sortable home_library_cards
|
||||||
function set_home_library_cards() {
|
function set_home_library_cards() {
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
<body>
|
<body>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="wizard" id="some-wizard" data-title="Tautulli Setup Wizard">
|
<div class="wizard" id="setup-wizard" data-title="Tautulli Setup Wizard">
|
||||||
<form>
|
<form>
|
||||||
<div class="wizard-card" data-cardname="card1">
|
<div class="wizard-card" data-cardname="card1">
|
||||||
<div style="float: right;">
|
<div style="float: right;">
|
||||||
|
@ -82,17 +82,21 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" class="form-control pms-auth" name="pms_token" id="pms_token" value="${config['pms_token']}" data-validate="validatePMStoken">
|
<input type="hidden" class="form-control pms-auth" name="pms_token" id="pms_token" value="" data-validate="validatePMStoken">
|
||||||
<a class="btn btn-dark" id="pms-authenticate" href="#" role="button">Authenticate</a><span style="margin-left: 10px; display: none;" id="pms-token-status"></span>
|
<a class="btn btn-dark" id="pms-authenticate" href="#" role="button">Authenticate</a><span style="margin-left: 10px; display: none;" id="pms-token-status"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="wizard-card" data-cardname="card3">
|
<div class="wizard-card" data-cardname="card3">
|
||||||
<h3>Plex Media Server</h3>
|
<h3>Plex Media Server</h3>
|
||||||
<p class="help-block">Enter your Plex Server details and then click the Verify button to make sure Tautulli can reach the server.</p>
|
<p class="help-block">
|
||||||
|
Select your Plex Media Server from the dropdown menu or enter an IP address or hostname.
|
||||||
|
</p>
|
||||||
<div class="wizard-input-section">
|
<div class="wizard-input-section">
|
||||||
<label for="pms_ip">Plex IP or Hostname</label>
|
<label for="pms_ip">Plex IP or Hostname</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12">
|
<div class="col-xs-12">
|
||||||
<select class="form-control wizard-pms-ip" id="pms_ip" name="pms_ip"></select>
|
<select class="form-control selectize-pms-ip" id="pms_ip" name="pms_ip">
|
||||||
|
<option value="${config['pms_ip']}" selected>${config['pms_ip']}</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -105,14 +109,14 @@
|
||||||
<div class="col-xs-4">
|
<div class="col-xs-4">
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="pms_ssl" name="pms_ssl" value="1"> Use SSL
|
<input type="checkbox" id="pms_ssl" name="pms_ssl" value="1" ${config['pms_ssl']}> Use SSL
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-4">
|
<div class="col-xs-4">
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="pms_is_remote" name="pms_is_remote" value="1"> Remote Server
|
<input type="checkbox" id="pms_is_remote" name="pms_is_remote" value="1" ${config['pms_is_remote']}> Remote Server
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -200,127 +204,6 @@
|
||||||
<script src="${http_root}js/script.js${cache_param}"></script>
|
<script src="${http_root}js/script.js${cache_param}"></script>
|
||||||
<script src="${http_root}js/bootstrap-wizard.min.js"></script>
|
<script src="${http_root}js/bootstrap-wizard.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
$(document).ready(function() {
|
|
||||||
|
|
||||||
$.fn.wizard.logging = false;
|
|
||||||
var options = {
|
|
||||||
keyboard : false,
|
|
||||||
contentHeight : 400,
|
|
||||||
contentWidth : 700,
|
|
||||||
backdrop: 'static',
|
|
||||||
buttons: {submitText: 'Finish'},
|
|
||||||
submitUrl: "configUpdate"
|
|
||||||
};
|
|
||||||
var wizard = $("#some-wizard").wizard(options);
|
|
||||||
wizard.show();
|
|
||||||
|
|
||||||
wizard.on("submit", function(wizard) {
|
|
||||||
// Probably should not success before we know, but hopefully validation is good enough.
|
|
||||||
wizard.submitSuccess();
|
|
||||||
$.ajax({
|
|
||||||
url: "configUpdate",
|
|
||||||
type: "POST",
|
|
||||||
url: wizard.args.submitUrl,
|
|
||||||
data: wizard.serialize(),
|
|
||||||
dataType: "json",
|
|
||||||
complete: function (data) {
|
|
||||||
$(".countdown").countdown(function () { location.reload(); }, 5, "");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
$select_pms = $('#pms_ip').selectize({
|
|
||||||
create: true,
|
|
||||||
createOnBlur: true,
|
|
||||||
openOnFocus: true,
|
|
||||||
maxItems: 1,
|
|
||||||
closeAfterSelect: true,
|
|
||||||
onInitialize: function () {
|
|
||||||
var s = this;
|
|
||||||
this.revertSettings.$children.each(function () {
|
|
||||||
$.extend(s.options[this.value], $(this).data());
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
render: {
|
|
||||||
item: function (item, escape) {
|
|
||||||
// first item is rendered before initialization bug?
|
|
||||||
if (!item.ci) {
|
|
||||||
$.extend(item, $(this.revertSettings.$children)
|
|
||||||
.filter('[value="' + item.value + '"]').data());
|
|
||||||
}
|
|
||||||
var label = item.label || item.value;
|
|
||||||
var caption = item.label ? item.value : null;
|
|
||||||
return '<div data-use_ssl="' + item.httpsRequired +
|
|
||||||
'" data-local="' + item.local +
|
|
||||||
'" data-ci="' + item.clientIdentifier +
|
|
||||||
'" data-ip="' + item.ip +
|
|
||||||
'" data-port="' + item.port +
|
|
||||||
'" data-label="' + item.label + '">' +
|
|
||||||
'<span class="item-text">' + escape(label) + '</span>' +
|
|
||||||
(caption ? '<span class="item-value">' + escape(caption) + '</span>' : '') +
|
|
||||||
'</div>';
|
|
||||||
},
|
|
||||||
option: function (item, escape) {
|
|
||||||
var label = item.label || item.value;
|
|
||||||
var caption = item.label ? item.value : null;
|
|
||||||
return '<div data-use_ssl="' + item.httpsRequired +
|
|
||||||
'" data-local="' + item.local +
|
|
||||||
'" data-ci="' + item.clientIdentifier +
|
|
||||||
'" data-ip="' + item.ip +
|
|
||||||
'" data-port="' + item.port +
|
|
||||||
'" data-label="' + item.label + '">' +
|
|
||||||
escape(label) +
|
|
||||||
(caption ? '<span class="caption">' + escape(caption) + '</span>' : '') +
|
|
||||||
'</div>';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
create: function(input) {
|
|
||||||
return {label: '', value: input};
|
|
||||||
},
|
|
||||||
onChange: function (item) {
|
|
||||||
var ci = $('.selectize-input').find('div').attr('data-ci');
|
|
||||||
var port = $('.selectize-input').find('div').attr('data-port')
|
|
||||||
var local = $('.selectize-input').find('div').attr('data-local')
|
|
||||||
var ssl = $('.selectize-input').find('div').attr('data-use_ssl')
|
|
||||||
|
|
||||||
$("#pms-verify-status").html("");
|
|
||||||
// If a option was added by a user its
|
|
||||||
// data-xxx="undefined"
|
|
||||||
if (ci != "undefined") {
|
|
||||||
// To allow next step in the guide.
|
|
||||||
// servers with clientIdentifier is verified
|
|
||||||
$("#pms_identifier").val(ci);
|
|
||||||
$("#pms_valid").val("valid");
|
|
||||||
$("#pms-verify-status").html('<i class="fa fa-check"></i> Server found!').show();
|
|
||||||
} else {
|
|
||||||
// Self made options must be verified
|
|
||||||
$("#pms_valid").val("");
|
|
||||||
$("#pms-verify-status").html("").hide();
|
|
||||||
}
|
|
||||||
// If the server is verified set the correct port
|
|
||||||
if (port != "undefined") {
|
|
||||||
$('#pms_port').val(port);
|
|
||||||
} else {
|
|
||||||
// set default port
|
|
||||||
$('#pms_port').val("32400");
|
|
||||||
}
|
|
||||||
if (local != "undefined" && local == '0') {
|
|
||||||
$('#pms_is_remote').prop('checked', true);
|
|
||||||
} else {
|
|
||||||
$('#pms_is_remote').prop('checked', false);
|
|
||||||
}
|
|
||||||
if (ssl != "undefined" && ssl == "1") {
|
|
||||||
$('#pms_ssl').prop('checked', true);
|
|
||||||
} else {
|
|
||||||
$('#pms_ssl').prop('checked', false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
function validatePMSip(el) {
|
function validatePMSip(el) {
|
||||||
var valid_pms_ip = el.val();
|
var valid_pms_ip = el.val();
|
||||||
var retValue = {};
|
var retValue = {};
|
||||||
|
@ -373,6 +256,114 @@
|
||||||
return $.isNumeric(n) && (Math.floor(n) == n) && (n >= 0)
|
return $.isNumeric(n) && (Math.floor(n) == n) && (n >= 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
$.fn.wizard.logging = false;
|
||||||
|
var options = {
|
||||||
|
keyboard : false,
|
||||||
|
contentHeight : 400,
|
||||||
|
contentWidth : 700,
|
||||||
|
backdrop: 'static',
|
||||||
|
buttons: {submitText: 'Finish'},
|
||||||
|
submitUrl: "configUpdate"
|
||||||
|
};
|
||||||
|
var wizard = $("#setup-wizard").wizard(options);
|
||||||
|
$('.btn.wizard-back').addClass('btn-dark');
|
||||||
|
wizard.show();
|
||||||
|
|
||||||
|
wizard.on("submit", function(wizard) {
|
||||||
|
// Probably should not success before we know, but hopefully validation is good enough.
|
||||||
|
wizard.submitSuccess();
|
||||||
|
$.ajax({
|
||||||
|
url: "configUpdate",
|
||||||
|
type: "POST",
|
||||||
|
url: wizard.args.submitUrl,
|
||||||
|
data: wizard.serialize(),
|
||||||
|
dataType: "json",
|
||||||
|
complete: function (data) {
|
||||||
|
$(".countdown").countdown(function () { location.reload(); }, 5, "");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
var $select_pms = $('#pms_ip').selectize({
|
||||||
|
createOnBlur: true,
|
||||||
|
openOnFocus: true,
|
||||||
|
maxItems: 1,
|
||||||
|
closeAfterSelect: true,
|
||||||
|
sortField: 'label',
|
||||||
|
searchField: ['label', 'value'],
|
||||||
|
inputClass: 'form-control selectize-input',
|
||||||
|
render: {
|
||||||
|
item: function (item, escape) {
|
||||||
|
var label = item.label || item.value;
|
||||||
|
var caption = item.label ? item.value : null;
|
||||||
|
return '<div data-ssl="' + item.httpsRequired +
|
||||||
|
'" data-local="' + item.local +
|
||||||
|
'" data-identifier="' + item.clientIdentifier +
|
||||||
|
'" data-ip="' + item.ip +
|
||||||
|
'" data-port="' + item.port +
|
||||||
|
'" data-label="' + item.label + '">' +
|
||||||
|
'<span class="item-text">' + escape(label) + '</span>' +
|
||||||
|
(caption ? '<span class="item-value">' + escape(caption) + '</span>' : '') +
|
||||||
|
'</div>';
|
||||||
|
},
|
||||||
|
option: function (item, escape) {
|
||||||
|
var label = item.label || item.value;
|
||||||
|
var caption = item.label ? item.value : null;
|
||||||
|
return '<div data-ssl="' + item.httpsRequired +
|
||||||
|
'" data-local="' + item.local +
|
||||||
|
'" data-identifier="' + item.clientIdentifier +
|
||||||
|
'" data-ip="' + item.ip +
|
||||||
|
'" data-port="' + item.port +
|
||||||
|
'" data-label="' + item.label + '">' +
|
||||||
|
escape(label) +
|
||||||
|
(caption ? '<span class="caption">' + escape(caption) + '</span>' : '') +
|
||||||
|
'</div>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
create: function(input) {
|
||||||
|
return {label: '', value: input};
|
||||||
|
},
|
||||||
|
onChange: function (item) {
|
||||||
|
var pms_ip_selected = this.getItem(item)[0];
|
||||||
|
var identifier = $(pms_ip_selected).data('identifier');
|
||||||
|
var port = $(pms_ip_selected).data('port');
|
||||||
|
var local = $(pms_ip_selected).data('local');
|
||||||
|
var ssl = $(pms_ip_selected).data('ssl');
|
||||||
|
|
||||||
|
$("#pms_valid").val((identifier !== 'undefined' ? 'valid' : ''));
|
||||||
|
$("#pms-verify-status").html((identifier !== 'undefined' ? '<i class="fa fa-check"></i> Server found!' : '')).fadeIn('fast');
|
||||||
|
|
||||||
|
$("#pms_identifier").val(identifier !== 'undefined' ? identifier : '');
|
||||||
|
$('#pms_port').val((port !== 'undefined' ? port : 32400));
|
||||||
|
$('#pms_is_remote').prop('checked', (local !== 'undefined' && local === 0));
|
||||||
|
$('#pms_ssl').prop('checked', (ssl !== 'undefined' && ssl === 1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var select_pms = $select_pms[0].selectize;
|
||||||
|
|
||||||
|
function getServerOptions(token) {
|
||||||
|
/* Set token and returns server options */
|
||||||
|
$.ajax({
|
||||||
|
url: 'discover',
|
||||||
|
data: {
|
||||||
|
token: token
|
||||||
|
},
|
||||||
|
success: function (result) {
|
||||||
|
if (result) {
|
||||||
|
var existing_value = $('#pms_ip').val();
|
||||||
|
result.forEach(function (item) {
|
||||||
|
if (item.value === existing_value) {
|
||||||
|
select_pms.updateOption(item.value, item);
|
||||||
|
} else {
|
||||||
|
select_pms.addOption(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
var pms_verified = false;
|
var pms_verified = false;
|
||||||
var authenticated = false;
|
var authenticated = false;
|
||||||
|
|
||||||
|
@ -465,39 +456,7 @@
|
||||||
$('#pms-token-status').fadeIn('fast');
|
$('#pms-token-status').fadeIn('fast');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
// Send database path to import script
|
|
||||||
//$("#plexwatch-import").click(function() {
|
|
||||||
// var database_path = $("#db_location").val();
|
|
||||||
// var table_name = 'processed';
|
|
||||||
// var import_ignore_interval = 0;
|
|
||||||
// $.ajax({
|
|
||||||
// url: 'get_plexwatch_export_data',
|
|
||||||
// data: {database_path: database_path, table_name:table_name, import_ignore_interval:import_ignore_interval},
|
|
||||||
// cache: false,
|
|
||||||
// async: true,
|
|
||||||
// success: function(data) {
|
|
||||||
// if (data === 'Import has started. Check the Tautulli logs to monitor any problems.') {
|
|
||||||
// $("#plexwatch-import-status").html('Started');
|
|
||||||
// } else {
|
|
||||||
// $("#plexwatch-import-status").html(data);
|
|
||||||
// }
|
|
||||||
// $("#db_location").val('')
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
//});
|
|
||||||
|
|
||||||
function getServerOptions(token) {
|
|
||||||
/* Set token and returns server options */
|
|
||||||
$.ajax({
|
|
||||||
url: "discover/" + token,
|
|
||||||
success: function (result) {
|
|
||||||
$('#pms_ip').html("");
|
|
||||||
// Add all servers to the "combobox"
|
|
||||||
$select_pms[0].selectize.addOption(result);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -85,9 +85,9 @@ class HTTPHandler(object):
|
||||||
if uri:
|
if uri:
|
||||||
request_urls = [urljoin(url, self.uri) for url in self.urls]
|
request_urls = [urljoin(url, self.uri) for url in self.urls]
|
||||||
|
|
||||||
if no_token and headers:
|
if no_token:
|
||||||
self.headers = headers
|
self.headers.pop('X-Plex-Token', None)
|
||||||
elif headers:
|
if headers:
|
||||||
self.headers.update(headers)
|
self.headers.update(headers)
|
||||||
|
|
||||||
responses = []
|
responses = []
|
||||||
|
|
|
@ -646,7 +646,8 @@ class PlexTV(object):
|
||||||
'ip': helpers.get_xml_attr(c, 'address'),
|
'ip': helpers.get_xml_attr(c, 'address'),
|
||||||
'port': helpers.get_xml_attr(c, 'port'),
|
'port': helpers.get_xml_attr(c, 'port'),
|
||||||
'local': helpers.get_xml_attr(c, 'local'),
|
'local': helpers.get_xml_attr(c, 'local'),
|
||||||
'value': helpers.get_xml_attr(c, 'address')
|
'value': helpers.get_xml_attr(c, 'address'),
|
||||||
|
'is_cloud': is_cloud
|
||||||
}
|
}
|
||||||
clean_servers.append(server)
|
clean_servers.append(server)
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ class WebInterface(object):
|
||||||
@cherrypy.tools.json_out()
|
@cherrypy.tools.json_out()
|
||||||
@requireAuth(member_of("admin"))
|
@requireAuth(member_of("admin"))
|
||||||
@addtoapi("get_server_list")
|
@addtoapi("get_server_list")
|
||||||
def discover(self, token=None, include_cloud=True, all_servers=False, **kwargs):
|
def discover(self, token=None, include_cloud=True, all_servers=True, **kwargs):
|
||||||
""" Get all your servers that are published to Plex.tv.
|
""" Get all your servers that are published to Plex.tv.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -148,7 +148,7 @@ class WebInterface(object):
|
||||||
plexpy.CONFIG.write()
|
plexpy.CONFIG.write()
|
||||||
|
|
||||||
include_cloud = not (include_cloud == 'false')
|
include_cloud = not (include_cloud == 'false')
|
||||||
all_servers = (all_servers == 'true')
|
all_servers = not (all_servers == 'false')
|
||||||
|
|
||||||
plex_tv = plextv.PlexTV()
|
plex_tv = plextv.PlexTV()
|
||||||
servers_list = plex_tv.discover(include_cloud=include_cloud,
|
servers_list = plex_tv.discover(include_cloud=include_cloud,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue