//*******************************************************************************
// * Copyright (c) 2017 Genialist Software Ltd.
// * All rights reserved.
// ******************************************************************************/
// depends: library-min.js
const pServer = new (function() {
var that = this, m_id = ''+Math.random();
//*** INIT
objects.put(m_id, this);
function f_login() {
pDocument.wait();
pConsole.info(that, "Contacting server...");
var i_request = new XMLHttpRequest();
i_request.timeout = 2000;
i_request.ontimeout = function() {
pDocument.wait();
pConsole.info(that, "Timeout on contacting server...");
setTimeout(f_login, 1000);
};
i_request.onerror = function() {
pDocument.wait();
pConsole.info(that, "Error on contacting server...");
setTimeout(f_login, 1000);
};
i_request.onreadystatechange = function(p_event) {
var i_xml_http_request = p_event.target;
if (i_xml_http_request.readyState === 4) {
if (pROSE.handleHTTPResponse(i_xml_http_request) === false)
return false;
}
};
i_request.open("GET", "/server", true);
i_request.send();
}
this.reboot = function() {
pDialog.question({ id: 'reboot-server' }).then(function() {
pDocument.wait();
pHTTPRequest.get(pURL.addQueryParameter('/server', [ 'action', 'reboot', 'v', Math.random() ]), function(i_request) {
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
//this is login URL...
setTimeout(f_login, 30000);
/*setTimeout(function() {
windows.location.reload(true);
var i_request = new XMLHttpRequest();
i_request.timeout = 10000;
i_request.ontimeout(function() {
}
}, 10000);*///pLocation.assign(this.url); }, 60000);
}, false);
});
};
this.shutdown = function() {
pDialog.question({ id: 'shutdown-server' }).then(function() {
pDocument.wait();
pHTTPRequest.get(pURL.addQueryParameter('/server', [ 'action', 'shutdown', 'v', Math.random() ]), function(i_request) {
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
//this is login URL...
var i_url = "/login?url="+encodeURI(pLocation.getPathAndQuery());
setTimeout(function() { pLocation.assign(i_url); }, 10000);
}, false);
});
};
this.clearCache = function() {
return new Promise(function(resolve, reject) {
pTransaction.transaction({
trace: that, url: pURL.addQueryParameter('/server', [ 'action', 'clear-cache', 'v', Math.random() ]), method_name: "ClearCache", responseType: 'text',
msg_start: 'Clearing Server Cache...',
msg_error: [ 'Clearing Server Cache... Failure', reject ],
msg_end: resolve || c_do_nothing
});
});
};
this.reclaimMemory = function() {
return new Promise(function(resolve, reject) {
pTransaction.transaction({
trace: that, url: pURL.addQueryParameter('/server', [ 'action', 'reclaim-memory', 'v', Math.random() ]), method_name: "ReclaimMemory", responseType: 'text',
msg_start: 'Reclaiming JVM Memory...',
msg_error: [ 'Reclaiming JVM Memory... Failure', reject ],
msg_end: resolve || c_do_nothing
});
});
};
this.createPortNumberDialogOption = function(id, text) {
return { id: id, className: 'dialog-question-input-inline', input: { type: 'number', min: 1, max: 65535 }, text: text };
};
this.startAuth = function(p_id, p_params) {
pTransaction.transaction({
trace: this, url: pURL.addQueryParameter(pURL.addQueryParameter('/server', [ 'action', 'start-auth', 'id', p_id, 'v', Math.random() ]), p_params), method_name: "Authenticate",
msg_start: 'Authenticating...',
msg_error: 'Authenticating... Failure',
msg_end: function(p_request) {
//handle errors
if (pROSE.handleHTTPResponse(p_request) === false)
return false;
var i_obj = pJSON.parse(p_request.responseText);
if (i_obj.url)
pLocation.assign(i_obj.url);
}
});
};
this.getProperties = function(p_request_pp) {
if (!pApplicationUI.canShowDialog())
return;
pDocument.wait();
if (!p_request_pp) p_request_pp = {};
p_request_pp.library = this;
var i_url = /*'http://' + pLocation.getHostname() + ':' + server_nossl_port +*/ pURL.addQueryParameter('/server', [ 'action', 'get-properties', 'format', 'json', 'contents', 'values', 'v', Math.random() ]);
pConsole.info(this, "GetProperties: " + i_url);
pHTTPRequest.get(i_url, function(i_request, i_data) {
var p_request_pp = this;
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
//console.log(i_request.responseText);
//pConsole.debug(that, "GetMetadata: response: " + pJSON.pretty(i_request.responseText));
var i_obj = pJSON.parse(i_request.responseText);
pConsole.debug(that, "GetProperties: response: " + pJSON.pretty(i_request.responseText));
var i_values = new pMap(i_obj.values);
var i_api_key_input = { type: 'text', placeholder: 'Enter your own, if empty, the server will use a default value...' };
var i_warn = { id: 'desc-warn', sep: true, className: 'warning', text: 'This tab settings will only apply after you restart the server.<p>' };
var i_style = 'width: 90px; min-width: 90px !important; max-width: 90px !important;';
var f_update = function() {
pDialog.resources.f_enableIfEnabled('server-properties', 'http_ssl_enabled', [ 'http_ssl_port_enabled', 'http_ssl_port', 'http_ssl_protocol', 'http_ssl_jks_file', 'http_ssl_jks_type', 'http_ssl_jks_provider', 'http_ssl_jks_password', 'http_ssl_key_password' ]);
pDialog.resources.f_disableIfEnabled('server-properties', 'java_net_useSystemProxies', [ 'http_proxyHost', 'http_proxyPort', 'https_proxyHost', 'https_proxyPort', 'http_nonProxyHosts' ]);
pDialog.resources.f_enableIfEnabled('server-properties', 'jmdns_enabled', [ 'name' ]);
pDialog.resources.f_enableIfEnabled('server-properties', 'http_transfer_encoding_gzip_enabled', [ 'http_transfer_encoding_gzip_minsize', 'http_transfer_encoding_gzip_mime_types' ]);
pDialog.resources.f_disableIfEnabled('server-properties', 'transcoder_ffmpeg_exe_plugin', [ 'transcoder_ffmpeg_exe_file' ]);
};
var i_dialog = {
id: 'server-properties',
title: p_request_pp.title,
options: [
'ok',
'cancel',
{ id: 'tab-http', tab: true, text: 'HTTP' },
i_warn,
'The hostname that clients must use to connect.<ul><li>:: means they can use any IP4 or IP6 hostname or address.<li>127.0.0.1 or 0.0.0.0 means they can use any IP4 hostname or address.',
{ id: "http_transport_default_host", className: 'dialog-question-input-inline2', input: { type: 'text', placeholder: 'Hostname/IP Address to listen to...' }, text: 'Hostname:' },
pServer.createPortNumberDialogOption("http_transport_default_port", 'Port Number:'),
/*"http_auth_default_enabled",false,
"http_auth_default_realm","Media Library HTTP Server (Authentication Required)",
"http_auth_default_login","admin",
"http_auth_default_password","admin",*/
'<hr>',
'<div style="margin-bottom: 8px;">SSL</div>',
{ id: "http_ssl_enabled", input: { type: 'checkbox', onchange: f_update }, text_after: 'Enable SSL', text_after_class: 'library-properties-checkbox' },
{ id: "http_ssl_port_enabled", input: { type: 'checkbox' }, text_after: 'Enable SSL on a separate port (below)', text_after_class: 'library-properties-checkbox' },
//{ id: "http_ssl_port", className: 'dialog-question-input-inline', input: { type: 'number', min: 1, max: 65535 }, text: 'SSL Port Number:' },
pServer.createPortNumberDialogOption("http_ssl_port", 'SSL Port Number:'),
{ id: "http_ssl_protocol", className: 'dialog-question-input-inline', input: { type: 'select', options: [ 'TLSv1.2', 'TLSv1.1', 'TLSv1', 'TLS', 'SSLv3', 'SSLv2', 'SSL' ] }, text: 'Protocol:' },
'<hr>',
'<div style="margin-bottom: 8px;">SSL Keystore</div>',
'The file containing the private key and public certificate the server will present to clients.<br>If empty, the server will generate a random one (with a self-signed certificate) when starting.<p>',
{ id: "http_ssl_jks_file", input: { type: 'server-file' }, text: 'File:' },
{ id: "http_ssl_jks_type", className: 'dialog-question-input-inline', input: { type: 'select', options: [ 'JCEKS', 'JKS', 'DKS', 'PKCS11', 'PKCS12' ]}, text: ' File Type/Format:' },
{ id: "http_ssl_jks_provider", className: 'dialog-question-input-inline', input: { type: 'select', options: i_obj.security_providers.map(function(i_pr) { return { text: i_pr.name, title: (i_pr.info)? i_pr.info + ((i_pr.version)? ', Version '+i_pr.version:'') : null }; }) }, text: 'Security Provider:' },
{ id: "http_ssl_jks_password", input: { type: 'password' }, text: 'Keystore Password:' },
'<hr>',
//{ id: "http_ssl_key_name", input: { }, text: 'Key/Alias Name:' },
{ id: "http_ssl_key_password", input: { type: 'password' }, text: 'Key/Alias Password:' },
{ id: 'tab-http-advanced', tab: true, text: 'HTTP Advanced' },
i_warn,
'<div style="margin-bottom: 8px;">Threads</div>',
{ id: 'http_thread_pool_minsize', className: 'dialog-question-input-inline', input: { type: 'number', min: 0, max: 65535, xstyle: i_style }, text: 'Minimum pool size:', label: { style: 'width: 240px;' } },
{ id: 'http_thread_pool_maxsize', className: 'dialog-question-input-inline', input: { type: 'number', min: 0, max: 65535, xstyle: i_style }, text: 'Maximum pool size:', label: { style: 'width: 240px;' } },
{ id: 'http_thread_pool_timeout', className: 'dialog-question-input-inline', input: { type: 'number', min: 0, max: 65535, xstyle: i_style }, text: 'Actitity Timeout (ms):', label: { style: 'width: 240px;' } },
{ id: 'http_thread_pool_prestart_one', xclassName: 'dialog-question-input-inline', input: { type: 'checkbox' }, text_after: 'Start one thread upon startup', text_after_class: 'library-properties-checkbox' },
{ id: 'http_thread_pool_prestart_all', xclassName: 'dialog-question-input-inline', input: { type: 'checkbox' }, text_after: 'Start all threads upon startup', text_after_class: 'library-properties-checkbox' },
'<hr>',
'<div style="margin-bottom: 8px;">Timeouts</div>',
{ id: 'http_connection_read_timeout_ms', className: 'dialog-question-input-inline', input: { type: 'number', min: 0, max: 655350, xstyle: i_style }, text: 'Read Timeout (ms):', label: { style: 'width: 240px;' } },
{ id: 'http_connection_read_request_timeout_ms', className: 'dialog-question-input-inline', input: { type: 'number', min: 0, max: 65535, xstyle: i_style }, text: 'Read Request Timeout (ms):', label: { style: 'width: 240px;' } },
'<hr>',
'<div style="margin-bottom: 8px;">Socket Options</div>',
{ id: 'http_connection_so_rvcbuf_size', className: 'dialog-question-input-inline', input: { type: 'number', min: 0, max: 655350, xstyle: i_style }, text: 'Receiver Buffer Size (bytes):', label: { style: 'width: 240px;' } },
{ id: 'http_connection_so_sndbuf_size', className: 'dialog-question-input-inline', input: { type: 'number', min: 0, max: 655350, xstyle: i_style }, text: 'Send Buffer Size (bytes):', label: { style: 'width: 240px;' } },
pDialog.newCheckbox('http_connection_so_linger_enabled', 'Linger Timeout'),
{ id: 'http_connection_so_linger_ms', className: 'dialog-question-input-inline', input: { type: 'number', min: 0, max: 65535, xstyle: i_style }, text: 'Linger Timeout (ms):', label: { style: 'width: 240px;' } },
pDialog.newCheckbox('http_connection_so_tcp_nodelay', 'TCP No Delay'),
pDialog.newCheckbox('http_connection_so_reuse_address', 'Reuse Address'),
{ id: 'http_connection_so_timeout_ms', className: 'dialog-question-input-inline', input: { type: 'number', min: 0, max: 65535, xstyle: i_style }, text: 'Socket Timeout (ms):', label: { style: 'width: 240px;' } },
'<hr>',
'<div style="margin-bottom: 8px;">Server Socket Options</div>',
//{ id: 'http_transport_default_so_rvcbuf_size', className: 'dialog-question-input-inline', input: { type: 'number', min: 0, max: 655350, xstyle: i_style }, text: 'Receiver Buffer Size (bytes):', label: { style: 'width: 240px;' } },
{ id: 'http_transport_default_so_reuse_address', input: { type: 'checkbox' }, text_after: 'Reuse Address', text_after_class: 'library-properties-checkbox' },
//{ id: 'http_transport_default_so_timeout_ms', className: 'dialog-question-input-inline', input: { type: 'number', min: 0, max: 655350, xstyle: i_style }, text: 'Socket Timeout (ms):', label: { style: 'width: 240px;' } },
{ id: 'http_transport_default_so_backlog', className: 'dialog-question-input-inline', input: { type: 'number', min: -1, max: 65535, xstyle: i_style }, text: 'Backlog Queue Size:', label: { style: 'width: 240px;' } },
{ id: 'tab-http-content', tab: true, text: 'HTTP Content' },
i_warn,
pDialog.newCheckbox('http_transfer_encoding_gzip_enabled', 'Compress Replies (with gzip)', f_update),
{ id: 'http_transfer_encoding_gzip_minsize', className: 'dialog-question-input-inline', input: { type: 'number', min: 0, max: 65535, xstyle: i_style }, text: 'Minimum size before compression happens (bytes):', label: { style: 'width: 380px;'} },
{ id: 'http_transfer_encoding_gzip_mime_types', input: { }, text: 'Compress for those MIME types:' },
'<hr>',
{ id: 'http_transfer_encoding_br_enabled', input: { type: 'checkbox' }, text_after: 'Compress Replies (with brotli): This feature is unstable and may crash the server...', text_after_class: 'library-properties-checkbox' },
{ id: 'http_transfer_encoding_br_minsize', className: 'dialog-question-input-inline', input: { type: 'number', min: 0, max: 65535, xstyle: i_style }, text: 'Minimum size before compression happens (bytes):', label: { style: 'width: 380px;'} },
{ id: 'http_transfer_encoding_br_mime_types', input: { }, text: 'Compress for those MIME types:' },
{ id: 'tab-transcoder', tab: true, text: '<img width="16" heigh="16" src="/resources/html/images/16x16/microformats.png" style="padding-right: 10px;"/>Transcoding' },
'Transcoding transforms videos on the fly to match your device and network capabilities in term of format and performance.<p>Transcoded videos remain cached on disk.'+
'<p>You can see which files have been or are currently being transcoded by selecting <a href="/server?show=transcodings" target="_blank">Transcoding</a> in the Server Settings page...',
//{ id: "transcoder_object_(*)_enabled", input: { type: 'checkbox' }, text_after: 'Enable transcoding', text_after_class: 'library-properties-checkbox' },
'<hr>',
'<div style="margin-bottom: 8px;">FFmpeg (the software that transcodes)</div>',
pDialog.newCheckbox("transcoder_ffmpeg_exe_plugin", 'Use default executable', f_update),
{ id: "transcoder_ffmpeg_exe_file", input: { type: 'server-file' }, text: 'Use external program:' },
'<hr>',
'<div style="margin-bottom: 8px;">Disk Cache</div>',
{ id: 'transcoder_cache_(*)_size_max_bytes', className: 'dialog-question-input-inline', input: { type: 'number', min: 0 }, text: 'Cache size (bytes):' },
pDialog.newCheckbox('transcoder_cache_(*)_purge_failed_at_startup', 'Delete failed transcodings at startup'),
//{ id: 'tab-metadata', tab: true, text: 'Find Information' },
//{ id: 'tab-imdb', className: 'toolbar-imdb', sep: true, text: 'IMDB', style: 'margin-bottom: 8px;' },
//'Those settings configure the server plug-in for IMDB.<p>This plug-in allows retrieving information from the web site <a href="https://www.imdb.com" target="_blank">IMDB.com</a>.<p>',
//{ id: "pIMDBApi_api_(*)_url_base", input: i_api_key_input, text: 'Base URL' },
//'<hr>',
/*
{ id: 'tab-tmdb', className: 'toolbar-themoviedb', sep: true, text: 'The Movie Database', style: 'margin-bottom: 8px;' },
'Those settings configure the server plug-in for The Movie Database.<p>This plug-in allows retrieving information from the web site <a href="https://www.themoviedb.org" target="_blank">The Movie Database</a>.',
{ id: "pAPIClient_TMDB_api_(*)_api_key", input: i_api_key_input, text: 'API Key:' },
{ id: "pAPIClient_TMDB_api_(*)_url_base", input: i_api_key_input, text: 'Base URL:' },
'<hr>',
{ id: 'tab-ttvdb', className: 'toolbar-thetvdb', sep: true, text: 'TheTVDB.com', style: 'margin-bottom: 8px;' },
'Those settings configure the server plug-in for thetvdb.com.<p>This plug-in allows retrieving TV information from the web site <a href="http://www.thetvdb.com" target="_blank">TheTVDB.com</a>.',
{ id: "pAPIClient_TTVDB_api_(*)_api_key", input: i_api_key_input, text: 'API Key:' },
{ id: "pAPIClient_TTVDB_api_(*)_url_base", input: i_api_key_input, text: 'Base URL:' },
'<hr>',
{ id: 'tab-wiki', className: 'toolbar-wikipedia', sep: true, text: 'Wikipedia', style: 'margin-bottom: 8px;' },
'Those settings configure the server plug-in for Wikipedia.<p>This plug-in allows retrieving information from the web site <a href="https://www.wikipedia.org" target="_blank">Wikipedia</a>.',
{ id: "pAPIClient_WikipediaMedia_api_(*)_url_base", input: i_api_key_input, text: 'Base URL:' },
'<hr>',
{ id: 'tab-discogs', className: 'toolbar-discogs', sep: true, text: 'Discogs', style: 'margin-bottom: 8px;' },
'Those settings configure the server plug-in for Discogs.<p>This plug-in allows retrieving music information from the web site <a href="https://www.discogs.com" target="_blank">Discogs.com</a>.',
{ id: "pDiscogsApi_api_(*)_api_key", input: i_api_key_input, text: 'API Key:' },
{ id: "pDiscogsApi_api_(*)_api_secret", input: i_api_key_input, text: 'API Secret:' },
{ id: "pDiscogsApi_api_(*)_url_base", input: i_api_key_input, text: 'Base URL:' },
'<hr>',
{ id: 'tab-lastfm', className: 'toolbar-lastfm', sep: true, text: 'last.fm', style: 'margin-bottom: 8px;' },
'Those settings configure the server plug-in for last.fm.<p>This plug-in allows retrieving music information from the web site <a href="https://www.last.fm.com" target="_blank">last.fm</a>.',
{ id: "pAPIClient_LastFM_api_(*)_api_key", input: i_api_key_input, text: 'API Key:' },
{ id: "pAPIClient_LastFM_api_(*)_url_base", input: i_api_key_input, text: 'Base URL:' },*/
//'Authenticate: <a href="javascript:void(pServer.startAuth(\''+i_obj.auths[0]+'\'))">here</a>',
{ id: 'tab-tracing', tab: true, text: 'Log Files' },
'Configure what information appear in the log file:',
pDialog.newCheckbox('trace_error', 'Trace Errors', null, i_obj.trace_error),
pDialog.newCheckbox('trace_warn', 'Trace Warnings', null, i_obj.trace_warn),
pDialog.newCheckbox('trace_info', 'Trace Information', null, i_obj.trace_info),
pDialog.newCheckbox('trace_debug', 'Trace Debugging', null, i_obj.trace_debug),
{ id: 'tab-security', tab: true, text: 'Security', title: 'This is about security' },
//i_warn,
'You can limit all admin tasks (importing medias, changing them, managing the server, etc...) to web browsers and devices running on the server and using the address localhost...<p>This will prevent changes coming from any other machine.',
pDialog.newCheckbox('admin_loopback_only', 'Limit administration actions to localhost/loopback only'),
'<hr>',
{ id: 'desc-warn', sep: true, className: 'warning', text: 'These settings below will only apply after you restart the server.<p>' },
'<hr>You can limit connections from other machines by specifying a comma-separated list of IP addresses or hostnames below.<p>The blacklist contains addresses for which connection will be refused.<p>* in the blacklist mean no other machine can connect.<p>The whitelist contains addresses for which connection will be accepted, even if they match the addresses in the blacklist.<p>',
{ id: "http_hostname_blacklist", input: { type: 'textarea' }, text: 'Address Blacklist:' },
{ id: "http_hostname_whitelist", input: { type: 'textarea' }, text: 'Address Whitelist:' },
{ id: 'tab-proxy', tab: true, text: 'HTTP Proxy' },
'The server will use the proxy below for browsing the internet (if the hostname is not empty or "Use the Operating System Proxy" is selected):<p>',
{ id: 'http_proxyHost', className: 'dialog-question-input-inline2', input: {}, text: 'HTTP Hostname' },
pServer.createPortNumberDialogOption("http_proxyPort", 'HTTP Port:'),
//{ id: 'http_proxyPort', input: { type: 'number', min: 1, max: 65535 }, text: 'HTTP Port' },
'',
{ id: 'https_proxyHost', className: 'dialog-question-input-inline2', input: {}, text: 'HTTPS Hostname' },
pServer.createPortNumberDialogOption("https_proxyPort", 'HTTPS Port:'),
//{ id: 'https_proxyPort', input: { type: 'number', min: 1, max: 65535 }, text: 'HTTPS Port' },
'<hr>You can specify a comma-separated list of hostnames (with wildcard characters) that the server will browse without the proxy:<p>',
{ id: 'http_nonProxyHosts', input: {}, text: 'No Proxy' },
'<hr>',
pDialog.newCheckbox('java_net_useSystemProxies', 'Use the Operating System Proxy', f_update),
{ id: 'tab-advanced', tab: true, text: 'Advanced' },
'<div style="margin-bottom: 8px;">Apple Bonjour Network</div>',
pDialog.newCheckbox("jmdns_enabled", 'Show the server on the network', f_update),
{ id: "name", input: { type: 'text' }, text: 'Server friendly name' }
].filter(pObject.isNotNull),
submitChangedInputsOnly: true,
fcall: function(p_dialog) {
var i_data = this; //pMediaLibray.getMetadata
var i_url = pURL.addQueryParameter('/server', [ 'action', 'set-properties', 'v', Math.random() ]);
pConsole.info(this, "SetProperties: " + i_url);
pHTTPRequest.post({ url: i_url, headers: pHTTPRequest.headers_post, body: pURL.toFormSubmitBody(p_dialog.inputs, pMetadataDialog.transformToServer) });
}.bind(p_request_pp)
};
if (window.server_ui_show_dlna_settings == 'true')
pArray.append(i_dialog.options, [
'<hr>',
'<div style="margin-bottom: 8px;">DLNA/uPNP</div>',
{ id: "dlna_enabled", input: { type: 'checkbox', onchange: f_update }, text_after: 'Enable the DLNA/uPNP Server', text_after_class: 'library-properties-checkbox' },
'The hostname that clients must use to connect.<ul><li>:: means they can use any IP4 or IP6 hostname or address.<li>127.0.0.1 or 0.0.0.0 means they can use any IP4 hostname or address.',
{ id: "dlna_hostname", className: 'dialog-question-input-inline2', input: { type: 'text', placeholder: 'Hostname/IP Address to listen to...' }, text: 'Hostname:' },
]);
//*** UPDATE VALUES
i_dialog.options.forEach(function(op) {
if (op.id) {
if (op.id.indexOf('file-')==0) return;
if (op.id.indexOf('library-')==0) return;
//if (op.id.endsWith('_api_key')) return;
//if (op.id.endsWith('_api_secret')) return;
if (op.id.indexOf('trace_')==0) return;
op.value = pMetadataDialog.transformFromServer(op.id, i_values.getValue(op.id, ''));
}
});
pDocument.stopwait(); //TODO: inside dialogQuestion...
pDialog.dialogQuestion(i_dialog);//.doc_url = i_data.doc_url;
f_update();
}.bind(p_request_pp), false);
};
this.getParentalControls = function(p_name) {
pDocument.wait();
var i_data = {
library: this,
user_id: p_name || pResources.get('managed-username')
};
var i_url = pURL.addQueryParameter('/server', [ 'action', 'get-user', 'id', i_data.user_id, 'format', 'json', 'contents', 'values', 'v', Math.random() ]);
pConsole.info(this, "GetUser: " + i_url);
pHTTPRequest.get(i_url, function(i_request, i_data) {
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
//console.log(i_request.responseText);
//pConsole.debug(that, "GetMetadata: response: " + pJSON.pretty(i_request.responseText));
var i_obj = pJSON.parse(i_request.responseText);
//, "GetUser: response: " + pJSON.pretty(i_request.responseText));
var i_values = new pMap(i_obj.values);
var i_score = parseInt(i_values.getValue('pc.medias.rating.score.max', 0));
var i_dialog = {
id: 'user-pc',
radio: true,
options: [
'ok', 'cancel',
{ id: 'tab-main', tab: true, text: 'Main' },
{ id: "pc.medias.unrated.videos.hide", input: { type: 'checkbox' }, text_after: 'Hide unrated medias', text_after_class: 'library-properties-checkbox' },
{ id: "pc.medias.adult.hide", input: { type: 'checkbox' }, text_after: 'Hide adult medias', text_after_class: 'library-properties-checkbox' },
{ id: "pc.medias.explicit.hide", input: { type: 'checkbox' }, text_after: 'Hide explicit medias', text_after_class: 'library-properties-checkbox' },
{ id: 'tab-cert', tab: true, text: 'Certificates' },
{ id: "pc.medias.rating.score.max.hide", input: { type: 'checkbox' }, text_after: 'Hide medias with certification up to:', text_after_class: 'library-properties-checkbox' },
],
submitChangedInputsOnly: true,
fcall: function(p_dialog) {
var i_data = this;
pTransaction.simpleTransaction({
trace: this, url: pURL.addQueryParameter('/user-update', [ 'user', i_data.user_id, 'v', Math.random() ]), method_name: "UpdateUser",
msg_start: pPageData.resolve('Updating User {resources.managed-fullname}...'),
headers: pHTTPRequest.headers_post,
body: pURL.toFormSubmitBody(p_dialog.inputs)
});
}.bind(i_data)
};
var i_option_prev = null;
var i_score_done = false;
i_obj.content_ratings.forEach(function(i_rating) {
if (i_rating.country && i_rating.country.code == i_obj.country && i_rating.type == 'movie') {
i_dialog.options[i_dialog.options.length] = pMediaLibrary.createContentRatingOption(i_rating, true);
if (!i_score_done && i_rating.score > i_score && i_option_prev) {
i_option_prev.selected = true;
i_score_done = true;
}
i_option_prev = i_dialog.options[i_dialog.options.length-1];
}
});
//*** UPDATE VALUES
i_dialog.options.forEach(function(op) {
if (op && op.id)
op.value = /*pMetadataDialog.transformFromServer(op.id,*/ i_values.getValue(op.id, '');//);
});
pDocument.stopwait(); //TODO: inside dialogQuestion...
pDialog.dialogQuestion(i_dialog);//.doc_url = i_data.doc_url;
}, false, i_data);
};
this.setAccess = function(p_doc_url) {
pDocument.wait();
var i_data = {
library: this,
doc_url: p_doc_url || window.location.pathname
};
pHTTPRequest.get(pURL.addQueryParameter(i_data.doc_url, [ 'action', 'get-access', 'format', 'json', 'v', Math.random() ]), function(i_request, i_data) {
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
//try {
//console.log(i_request.responseText);
var i_obj = pJSON.parse(i_request.responseText);
i_data.obj = i_obj;
i_data.allow = i_obj.allow;
i_data.deny = i_obj.deny;
i_data.user_map = new pMap();
i_data.user_fullname_map = new pMap();
for(var i=0 ; i<i_obj.users.length ; i++) {
i_data.user_map.put(i_obj.users[i].name, i_obj.users[i]);
i_data.user_fullname_map.put(i_obj.users[i].fullname, i_obj.users[i]);
}
//alert("reply :" + pJSON.pretty(i_request.responseText));
//var i_data = pHTTPRequest.remove(i_requbannerest);
var i_dialog = {
id: 'set-access',
title: "Set Access...",
options: [
{ id: 'tab-allow', tab: true, text: 'Allow Access...' },
{ id: "allow-text", sep: true, text: 'Users in this list will have access to this page even if:<ul><li>they are in the denied list below<li>or parental control settings would prevent them from accessing it...</ul>' },
{ id: "allow", input: { oninput: function() {
var i_dialog = pDialog.getValue('set-access');
if (!i_dialog)
return;
i_data.allow = pMediaLibrary.parseUserList(pDialog.getInputValue('set-access', 'allow').split(','), i_data.user_fullname_map).split(',');
pDialog.setInputValue('set-access', 'allow', pMediaLibrary.formatUserList(i_data.allow, i_data.user_map));
}, icons: [
{
className: 'dialog-question-button-adduser',
title: 'Click here to add a user...',
onclick: function(oid, iid){
pMediaLibrary.selectUser(i_data.obj_users).then(function(u) {
if (!i_data.allow.includes(u))
i_data.allow.push(u);
pElement.x(iid).value = pMediaLibrary.formatUserList(i_data.allow, i_data.user_map);
});
}
}
]}, text: 'Users:', value: pMediaLibrary.formatUserList(i_data.allow, i_data.user_map) },
{ id: 'tab-deny', tab: true, text: 'Deny Access...', selected: true },
{ id: "deny-text", sep: true, text: 'Users in this list will not have access to this page even if:<ul><li>parental control settings would allow them accessing it...</ul>' },
{ id: "deny", input: { oninput: function() {
var i_dialog = pDialog.getValue('set-access');
if (!i_dialog)
return;
i_data.deny = pMediaLibrary.parseUserList(pDialog.getInputValue('set-access', 'deny').split(','), i_data.user_fullname_map).split(',');
pDialog.setInputValue('set-access', 'deny', pMediaLibrary.formatUserList(i_data.deny, i_data.user_map));
}, icons: [
{
className: 'dialog-question-button-adduser',
title: 'Click here to add a user...',
onclick: function(oid, iid){
pMediaLibrary.selectUser(i_data.obj.users).then(function(u) {
if (!i_data.deny.includes(u))
i_data.deny.push(u);
pElement.x(iid).value = pMediaLibrary.formatUserList(i_data.deny, i_data.user_map);
});
}
}
]}, text: 'Users:', value: pMediaLibrary.formatUserList(i_data.deny, i_data.user_map) },
'ok', 'cancel'
],
multiple: true,
fcall: function(p_dialog, p_value) {
//alert('here: ' + pString.concat(p_value, ','));
//for a multiple choice dialog, p_value is an array of the selected values...
var i_data = this;
//alert('deny: '+ pString.concat(i_data.deny, ','));
var i_url = pURL.addQueryParameter(i_data.doc_url, [ 'action', 'set-access', 'v', Math.random() ]);
pConsole.info(this, "SetAccess: " + i_url);
pHTTPRequest.invoke({
method: 'POST',
url: i_url,
headers: pHTTPRequest.headers_post,
body: 'allow='+pURL.fixedEncodeURIComponent(pString.concat(i_data.allow, ','))+'&deny='+pURL.fixedEncodeURIComponent(pString.concat(i_data.deny, ','))
});
//i_data.library.setMetadata(i_data.doc_url, 'metadata_tags', pString.concat(p_value, '|'));
}.bind(i_data)
};
pDocument.stopwait();
pDialog.dialogQuestion(i_dialog);
//}
}, false, i_data);
};
this.setLangs = function(p_doc_url) {
pDocument.wait();
var i_data = {};
pHTTPRequest.get(pURL.addQueryParameter('/server', [ 'action', 'get-properties', 'format', 'json', 'contents', 'values', 'v', Math.random() ]), function(i_request, i_data) {
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
//try {
//console.log(i_request.responseText);
var i_obj = pJSON.parse(i_request.responseText), i_values = new pMap(i_obj.values);
i_data.obj = i_obj;
i_data.langs = pString.split(i_values.getValue("langs_preferred", "en"), '|').map(function(i_lang) { return pLang.getLongName(i_lang).toLowerCase() });
var i_dialog = {
id: 'server-langs',
options: [
{ id: "langs-text", sep: true, text: 'The preferred languages are used when:<ul><li>retrieving media information from the internet...<li>when playing a movie with multiple language audio or subtitle tracks...</ul>' },
{ id: "langs", input: { oninput: function() {
var i_dialog = pDialog.getValue('server-langs');
if (!i_dialog)
return;
i_data.langs = pString.split(pServer.parseLangList(pString.split(pDialog.getInputValue('server-langs', 'langs'), ',')), ',');
pDialog.setInputValue('server-langs', 'langs', pServer.formatLangList(i_data.langs));
}, icons: [
{
className: 'dialog-question-button-addlang',
title: 'Click here to add a language...',
onclick: function(oid, iid){
var i_data = this;
pServer.selectLang(i_data.obj.langs, i_data.langs).then(function(l) {
l = l.toLowerCase();
if (!i_data.langs.includes(l))
i_data.langs.push(l);
pElement.x(iid).value = pServer.formatLangList(i_data.langs);
});
}.bind(i_data)
}
], datalist: (pApplicationUI.OPTION_DATALISTS)? pLang.getLangs().map(pString.capitalize).sort() : null
}, text: 'Preferred Languages:', value: pServer.formatLangList(i_data.langs) },
'ok', 'cancel'
],
fcall: function(p_dialog, p_value) {
pTransaction.simpleTransaction({
trace: this, url: pURL.addQueryParameter('/server', [ 'action', 'set-properties', 'v', Math.random() ]), methodName: 'SetPreferredLangs',
msg_start: 'Setting preferred languages...',
headers: pHTTPRequest.headers_post,
body: 'langs_preferred='+pURL.fixedEncodeURIComponent(pString.concat(this.langs, '|', false, pLang.getISOName))
});
}.bind(i_data)
};
pDocument.stopwait();
pDialog.dialogQuestion(i_dialog);
//}
}, false, i_data);
};
this.parseLangList = function(p_obj_users) {
return pString.concat(p_obj_users, ", ", false);
};
this.formatLangList = function(p_obj_users) {
return pString.concat(p_obj_users, ", ", false, pLang.display);//pString.capitalize);
};
this.selectLang = function(langs, excludes) {
return new Promise(function(resolve, reject) {
var d = {
id: 'select-lang',
options: ['cancel'],
};
langs.sort().forEach(function(l) {
if (pString.v(l) && !(excludes || []).includes(l.toLowerCase())) {
var iso = pLang.getISOName(l);//, nat = iso? pLang.nativex.getValue(iso) : null;
//if (iso)
// nat = pLang.nativex.getValue(iso);
d.options.push({
id: l,
value: l,
text: pLang.display(l),//(nat && nat!=l.toLowerCase())? pString.capitalize(nat) + ' ('+l+')' : l,
className: 'dialog-lang',
fcall: function(d, v) {
resolve(v);
}
});
}
});
pDocument.stopwait();
pDialog.dialogQuestion(d);
});
};
this.openLibrary = function() {
pOpenFileDialog.selectFolder({
title: 'Open Library... Select the folder containing the library...',
callback: function(p) {
var u = pURL.addQueryParameter('/server', [ 'action', 'open-library', 'path', p, 'v', Math.random() ]);
pConsole.info(that, "OpenLibrary: " + u);
pHTTPRequest.get(u, null, false);
if (pLibraryList) pLibraryList.update();
},
getOkText: function(p_dialog, p_file) {
//if (p_file.files)
if ((p_file.files || []).some(function(f) { return f.name == "4178918784091587936" }))
return "Open this Library";
/*for(var i=0 ; i<p_file.files.length ; i++) {
if (p_file.files[i].name == "4178918784091587936")
return "Open this Library";
}*/
//return null;
},
recents: pLibraryList.recents
});
};
});
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
const pServerStatus = (window.pLibraryUpdateInstance)? new pLibraryUpdateInstance('ServerStatus', 1000) : {};
pServerStatus.licenseExpirationText = function(i_obj) {
if (i_obj.expires) {
if (i_obj.expire_days) {
if (i_obj.expire_days==0)
return '<div class="warning">Your evaluation license will end at: '+pHumanText.toDateTime(pDate.create(i_obj.expires))+'.<p>'+
'Please visit <a class="link" href="https://www.genialist.tv" target="_blank">https://www.genialist.tv</a> to purchase a full license.<p>'+
'If you have downloaded your license ticket, click here for the server to acknowledge it: <span class="link" onclick="pServerStatus.getenv()">Refresh License<span></div>';
else if (i_obj.expire_days==1)
return '<div class="warning">Your evaluation license will end in 1 day.<p>'+
'Please visit <a class="link" href="https://www.genialist.tv" target="_blank">https://www.genialist.tv</a> to purchase a full license.<p>'+
'If you have downloaded your license ticket, click here for the server to acknowledge it: <span class="link" onclick="pServerStatus.getenv()">Refresh License<span></div>';
else
return '<div class="warning">Your evaluation license will end in '+i_obj.expire_days+' days.<p>'+
'Please visit <a class="link" href="https://www.genialist.tv" target="_blank">https://www.genialist.tv</a> to purchase a full license.<p>'+
'If you have downloaded your license ticket, click here for the server to acknowledge it: <span class="link" onclick="pServerStatus.getenv()">Refresh License<span></div>';
}
return '<div class="warning">Your evaluation license will end at: '+pDate.toLocaleString(pDate.create(i_obj.expires))+'.<p>'+
'Please visit <a class="link" href="https://www.genialist.tv" target="_blank">https://www.genialist.tv</a> to purchase a full license.<p>'+
'If you have downloaded your license ticket, click here for the server to acknowledge it: <span class="link" onclick="pServerStatus.getenv()">Refresh License<span></div>';
}
return '';
};
pServerStatus.getenv = function() {
pHTTPRequest.get('/server?action=refresh-license=&v='+Math.random()).then(pServerStatus.update).then(pAbout.update);
};
pServerStatus.updateImpl = function(resolve, reject, that) {
if (pDocument.isShown('server_status')===false) {
pDocument.clearTimeout(that.id);
return;
}
var u = '/server?action=get-status&contents=object';//&v='+Math.random();
pConsole.info(that, "GetStatus: " + u);
pHTTPRequest.invoke({ url: u, onerror: that.onerror }).then(function(i_request) {
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
if (i_request.status == 200 && that.needsRefresh(i_request.responseText)) {
var i_obj = pJSON.parse(i_request.responseText);
var i_total_pc = (100 * i_obj.memory.total ) / i_obj.memory.max;
var i_used_pc = (100 * (i_obj.memory.total - i_obj.memory.free)) / i_obj.memory.total;
var h = '';
h += '<div id="server-status-uptime" class="box">';
h += that.renderRefreshText();
h += '<div>Server started since: '+pHumanText.toDateTime(pDate.create(i_obj.started))+'</div>';
h += pServerStatus.licenseExpirationText(i_obj);
h += '</div>';
h += '<div id="server-status-memory" class="box">';
h += '<div id="server-status-memory-title">JVM Memory</div>';
h += '<div id="server-status-memory-content">';
h += '<div class="mem-item mem-used" >Used: '+pHumanText.toByteSize(i_obj.memory.total - i_obj.memory.free)+'</div>';
h += '<div class="mem-item mem-total">Total: '+pHumanText.toByteSize(i_obj.memory.total)+'</div>';
h += '<div class="mem-item mem-max">Maximum: '+pHumanText.toByteSize(i_obj.memory.max)+'</div>';
//h += '<div class="mem-item mem-reclaim link" onclick="pServer.reclaimMemory()">Reclaim Memory</div>';
h += '<div id="mem-max"><div id="mem-total" style="width: '+i_total_pc+'%"><div id="mem-used" style="width: '+i_used_pc+'%"/></div></div></div>';
h += '<div class="mem-item mem-reclaim link" onclick="pServer.reclaimMemory().then(pServerStatus.update)">Reclaim Memory</div>';
h += '</div>';
h += '</div>';
//h += '<div class="box">';
//h += '<div id="server-status-memory-title">Internal Cache</div>';
//h += '<div class="mem-item mem-reclaim link" onclick="pServer.clearCache()">Clear Cache</div>';
//h += '</div>';
if (i_obj.properties) {
h += '<div class="box">';
h += '<div id="server-status-memory-title">JVM System Properties</div>';
h += '<table class="simple table-name-value"><tr><th style="text-align: left;">Name</th><th style="text-align: left;">Value</th></tr>';
h += that.renderProperties(i_obj.properties);
h += '</table>';
h += '</div>';
}
if (i_obj.env) {
h += '<div class="box">';
h += '<div id="server-status-memory-title">Environment Variables</div>';
h += '<table class="simple table-name-value"><tr><th style="text-align: left;">Name</th><th style="text-align: left;">Value</th></tr>';
h += that.renderProperties(i_obj.env);
h += '</table>';
h += '</div>';
}
if (i_obj.fwrk_folder_temp)
h += '<div class="box">Temporary Folder: ' + i_obj.fwrk_folder_temp + '</div>';
if (i_obj.fwrk_folder_conf)
h += '<div class="box">Configuration Folder: ' + i_obj.fwrk_folder_conf + '</div>';
if (i_obj.fwrk_folder_local)
h += '<div class="box">Local Folder: ' + i_obj.fwrk_folder_local + '</div>';
pElement.setInnerHTML('server-status-content', h);
that.cache(i_request.responseText);
}
//*** RESOLVE PROMISE
resolve();
//*** CALL NEXT UPDATE
that.nextUpdate();
});
};
pServerStatus.renderProperties = function(p_properties) {
var h = '', i_map = new pMap(p_properties);
i_map.keys().slice(0).sort().forEach(function(n) {
h += '<tr><td data-label="Name">'+pString.encodeHTML(n)+'</td><td data-label="Value">';
if (n.toLowerCase().endsWith('path')) {
var i_value = i_map.getValue(n);
for(var j=0 ; j<i_value.length ; j++) {
h += pString.encodeHTML(i_value.charAt(j));
if (i_value.charAt(j)==';' || i_value.charAt(j)==';')
h += '<br/>';
}
}
else if (n == 'sun.java.command') {
var i_commands = i_map.getValue(n).split(' ');
for(var j=0 ; j<i_commands.length ; j++) {
h += pString.encodeHTML(i_commands[j]);
if (j+1<i_commands.length) h += '<br/>';
}
}
else
h += pString.encodeHTML(i_map.getValue(n));
h += '</td></tr>';
});
return h;
};
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
const pNetworkStatus = (window.pLibraryUpdateInstance)? new pLibraryUpdateInstance('NetworkStatus', 10000) : {};
pNetworkStatus.f_filter = function(i_net) { return i_net.addresses && i_net.addresses.length>0 };
pNetworkStatus.f_sort = function(a, b) { return (a.display < b.display)? -1 : (a.display > b.display)? 1 : 0; };
pNetworkStatus.updateImpl = function(resolve, reject, that) {
if (pDocument.isShown('network_status')===false) {
pDocument.clearTimeout(that.id);
return;
}
var u = '/server?action=get-networks&contents=object&v='+Math.random();
pConsole.info(that, "GetStatus: " + u);
pHTTPRequest.invoke({ url: u, onerror: that.onerror }).then(function(i_request) {
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
if (i_request.status == 200 && that.needsRefresh(i_request.responseText)) {
var i_obj = pJSON.parse(i_request.responseText);
var h = '<div class="box">';
h += that.renderRefreshText();
h += '<div>IP Address: ' + pString.encodeHTML(i_obj.nonssl_address) + '</div>';
h += '<div class="desc">Address the server is listening on. <br>If it equals to 0.0.0.0 (IPv4) or 0:0:0:0:0:0:0:0 (IPv6), the server can receive requests whatever the hostname clients are using in the HTTP/HTTPS url. <br>Otherwise, clients must use the specified address.</div>';
h += '</div>';
h += '<div class="box">Available Network Interfaces: <ol>';
i_obj.networks.filter(that.f_filter).sort(that.f_sort).forEach(function(i_net) {
h += '<li>'+pString.encodeHTML(i_net.display)+' ('+pString.encodeHTML(i_net.name)+')';
h += '<ul>';
i_net.addresses.forEach(function(i_addr) { h += '<li><span class="desc">'+pString.encodeHTML(i_addr)+'</span></li>'; });
h += '</ul></li>';
});
h += '</ol></div>';
pElement.setInnerHTML('network-status-content', h);
that.cache(i_request.responseText);
}
//*** RESOLVE PROMISE
resolve();
//*** CALL NEXT UPDATE
that.nextUpdate();
});
};
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
const pPluginList = (window.pLibraryUpdateInstance)? new pLibraryUpdateInstance('PluginList', 60000, 'plugins') : {};
pPluginList.updateImpl = function(resolve, reject, that) {
if (pDocument.isShown(that.element)===false) {
pDocument.clearTimeout(that.id);
return;
}
var u = '/server?action=get-status&v='+Math.random();
pConsole.info(that, "GetStatus: " + u);
pHTTPRequest.invoke({ url: u, onerror: that.onerror }).then(function(i_request) {
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
if (i_request.status == 200) {
//alert(pJSON.pretty(i_request.responseText));
const i_label_product = 'Product';
const i_label_version = 'Version';
const i_label_started = 'Started';
var i_obj = pJSON.parse(i_request.responseText);
var h = '';
h += that.renderRefreshText();
h += '<table class="table-plugins"><tr>';
//h += '<th/>';
h += '<th style="text-align: left;">'+i_label_product+'</th>';
h += '<th style="text-align: left;">'+i_label_version+'</th>';
h += '<th style="text-align: left;">'+i_label_started+'</th><th/> </tr>';
for(var i=0 ; i<i_obj.fwrk.plugins.plugins.length ; i++) {
var i_plugin = i_obj.fwrk.plugins.plugins[i].plugin;
var i_id = "'" + i_obj.fwrk.plugins.plugins[i].id + "'";
var i_pd = "'" + i_plugin.product + "'";
var i_v = "'" + i_plugin.version + "'";
h += '<tr>';
//h += '<td>';
//h += '<img class="image toolbar-icon" src="/resources/html/images/16x16/add_on.png"/>';
//h += '</td>';
h += '<td data-label="'+i_label_product+'"><img class="image toolbar-icon" src="/resources/html/images/16x16/add_on.png" style="vertical-align: middle; padding-right: 4px;"/>'+pString.encodeHTML(i_plugin.product)+'</td>';
h += '<td data-label="'+i_label_version+'">'+pString.encodeHTML(i_plugin.version)+'</td>';
h += '<td data-label="'+i_label_started+'">'+(i_plugin.started? 'yes':'no')+'</td>';
h += '<td>';
if (i_plugin.started === true && i_plugin.canStop === true)
h += '<span class="link" onclick="pPluginList.stop('+i_id+','+i_pd+','+i_v+')">Stop</span>';
else if (i_plugin.started === false && i_plugin.canStart === true)
h += '<span class="link" onclick="pPluginList.start('+i_id+','+i_pd+','+i_v+')">Start</span>';
h += '</td>';
h += '</tr>';
}
h += '</table>';
pElement.setInnerHTML(that.element, h);
}
//*** RESOLVE PROMISE
resolve();
//*** CALL NEXT UPDATE
that.nextUpdate();
});
};
pPluginList.bind("start", function(p_id, p_name, p_version) {
var i_url = '/server?action=start-plugin&id='+p_id+'&v='+Math.random()+'&wait=1';
pTransaction.transaction({
trace: this, url: i_url, method_name: "StopPlugin",
msg_start: 'Starting plugin '+p_name+' ('+p_version+')...',
msg_error: 'Plugin '+p_name+' ('+p_version+') has NOT been started...',
msg_end: 'Plugin '+p_name+' ('+p_version+') has been started...',
});
});
pPluginList.bind("stop", function(p_id, p_name, p_version) {
var i_url = '/server?action=stop-plugin&id='+p_id+'&v='+Math.random()+'&wait=1';
pTransaction.transaction({
trace: this, url: i_url, method_name: "StopPlugin",
msg_start: 'Stopping plugin '+p_name+' ('+p_version+')...',
msg_error: 'Plugin '+p_name+' ('+p_version+') has NOT been stopped...',
msg_end: 'Plugin '+p_name+' ('+p_version+') has been stopped...',
});
});
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
const pAbout = (window.pLibraryUpdateInstance)? new pLibraryUpdateInstance('About', null, 'about') : {};
pAbout.updateImpl = function(resolve, reject, that) {
if (pDocument.isShown(that.element)===false) {
pDocument.clearTimeout(that.id);
return;
}
var u = '/server?action=get-status&v='+Math.random();
pConsole.info(that, "GetStatus: " + u);
pHTTPRequest.invoke({ url: u, onerror: that.onerror }).then(function(i_request) {
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
if (i_request.status == 200 && that.needsRefresh(i_request.responseText)) {
var i_obj = pJSON.parse(i_request.responseText);
//alert(pJSON.pretty(JSON.stringify(i_obj.fwrk.plugins)));
var h = '';
h += '<div class="box">';
h += '<div class="header-title">';
h += '<div><img src="/favicon.png"/></div>\n';
h += '<div style="padding-top: 0px;">'+pString.encodeHTML(i_obj.name)+'</div>';
h += '</div>';
h += '<div class="desc" style="display: block;">Version: ' + pString.encodeHTML(i_obj.version)+'</div>';
h += '<div>Copyright (c) 2017, Genialist Software Ltd. All rights reserved.</div>';
h += '</div>';
h += '<div class="box"><div>Information</div>';
h += '<dl><dd><div class="desc" style="display: block; xpadding-left: 0px;">License agreement: <a class="link" href="/licenses/plugins/license-agreement.txt" target="_blank">License Agreement</a></div>';
h += '<dd><div class="desc" style="display: block; xpadding-left: 0px;">Web-Site: <a class="link" href="https://www.genialist.tv" target="_blank">https://www.genialist.tv</a></div>';
h += '</div>';
var i_expires = pServerStatus.licenseExpirationText(i_obj);
if (pString.v(i_expires))
h += '<div class="box">' + i_expires + '</div>';
h += '<div class="box"><div>Acknowledgements</div>';
h += '<dl><dd><div class="desc" style="display: block;">This software uses <a class="link" href="https://www.themoviedb.org" target="_blank">The Movie Database</a> web site and the TMDb API but is not endorsed or certified by TMDb.</div>';
h += '<dd><div class="desc" style="display: block;">This software uses <a class="link" href="http://www.thetvdb.com" target="_blank">TheTVDB.com</a> web site and the TheTVDB.com API but is not endorsed or certified by TheTVDB.com.</div>';
h += '<dd><div class="desc" style="display: block;">This software uses <a class="link" href="https://www.wikipedia.org" target="_blank">Wikipedia</a> web site but is not endorsed or certified by Wikipedia.</div>';
h += '<dd><div class="desc" style="display: block;">This software uses <a class="link" href="https://www.discogs.com" target="_blank">Discogs.com</a> web site and the Discogs.com API but is not endorsed or certified by Discogs.com.</div>';
h += '<dd><div class="desc" style="display: block;">This software uses <a class="link" href="https://www.last.fm.com" target="_blank">last.fm</a> web site and the last.fm API but is not endorsed or certified by last.fm.</div>';
h += '</div>';
h += '<div class="box"><div>Third Party Licenses</div>';
h += '<ul>'
h += '<li><div class="desc">Icons provided by Fat Cow Web Hosting, for more information, please visit <a class="link" href="http://www.fatcow.com/free-icons" target="_blank">http://www.fatcow.com/free-icons</a>.</div></li>';
var i_licenses = new pMap();
var i_names = new pMap();
i_obj.fwrk.plugins.plugins.forEach(function(p) {
if (p.licenses)
p.licenses.forEach(function(l) {
i_licenses.put(l.name+l.filename, l);
var i_l = i_names.getValue(l.name);
if (i_l) {
i_l.put(l.name+l.filename, l);
}
else
i_names.put(l.name, new pMap([ l.name+l.filename, l ]));
});
});
i_names.keys().sort(pString.compareIgnoreCase).forEach(function(n) {
var i_l = i_names.getValue(n);
if (i_l.length>1) {
h += '<li class="desc">'+n+'<ul>';
i_l.values().forEach(function(l) {
var i_path = l.relpath;
if (i_path.startsWith("http://") || i_path.startsWith("https://"))
h += '<li><div class="desc license"><a class="link xdesc" href="'+i_path+'\" target="_blank">'+pString.encodeHTML(pString.substring_after(l.filename, './'))+'</a></div></li>';
else
h += '<li><div class="desc license"><a class="link xdesc" href="/licenses/'+i_path+'\" target="_blank">'+pString.encodeHTML(pString.substring_after(l.filename, './'))+'</a></div></li>';
});
h += '</ul></li>';
}
else {
var i_path = i_l.values()[0].relpath;
if (i_path && (i_path.startsWith("http://") || i_path.startsWith("https://")))
h += '<li><div class="desc license"><a class="link xdesc" href="'+i_path+'\" target="_blank">'+pString.encodeHTML(n)+'</a></div></li>';
else
h += '<li><div class="desc license"><a class="link xdesc" href="/licenses/'+i_path+'\" target="_blank">'+pString.encodeHTML(n)+'</a></div></li>';
}
});
/*
i_licenses.keys().sort(pString.compareIgnoreCase).forEach(function(l) {
var i_path = i_licenses.getValue(l).relpath;
if (i_path) {
//console.log(i_path);
if (i_path.startsWith("http://") || i_path.startsWith("https://"))
h += '<li><div class="desc"><a class="link xdesc" href="'+i_path+'\" target="_blank">'+i_licenses.getValue(l).name+'</a></div></li>';
else
h += '<li><div class="desc"><a class="link xdesc" href="/licenses/'+i_path+'\" target="_blank">'+i_licenses.getValue(l).name+'</a></div></li>';
}
});*/
h += '</ul>'
h += '</div>';
pElement.setInnerHTML(that.element.id+'-content', h);
that.cache(i_request.responseText);
}
//*** RESOLVE PROMISE
resolve();
//*** CALL NEXT UPDATE
that.nextUpdate();
});
};
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
const re_lines = /(\r\n)|(\n)/;
const re_html = /</;
const pLogFile = (window.pLibraryUpdateInstance)? new pLibraryUpdateInstance('LogFile', 500) : { vprivate: {}};
pLogFile.maxlines = 1000;
pLogFile.updateImpl = function(resolve, reject, that) {
if (pDocument.isShown('server_logfile')===false) {
pDocument.clearTimeout(that.id);
return;
}
var u = '/server?action=get-logfile&v='+Math.random();
pConsole.info(that, "GetLogFile: " + u);
pHTTPRequest.invoke({ url: u, onerror: that.onerror }).then(function(i_request) {
//handle errors
if (pROSE.handleHTTPResponse(i_request, true) === false)
return false;
if (i_request.status == 200) {
if (!that.previous || that.previous != i_request.responseText) {
if (that.maxlines<1)
that.maxlines = 1;
var i_class = null;
var h = '';
var i_lines = i_request.responseText.split(re_lines);
//if (i_lines.length<2) i_lines = i_request.responseText.split('\n');
for(var i=(i_lines.length<that.maxlines)? 0 : i_lines.length-that.maxlines ; i<i_lines.length ; i++) {
var i_line = i_lines[i];
if (!i_line) continue;
if (i_line.indexOf('Rebooting')>0)
i_class = "log-line-rebooting";
else if (i_line.indexOf('[ERR')>0)
i_class = "log-line-error";
else if (i_line.indexOf('[WARN')>0)
i_class = "log-line-warning";
else if (i_line.indexOf('[INFO')>0)
i_class = null;
else if (i_line.indexOf('[INFO')>0)
i_class = null;
else if (i_line.indexOf('[DEBG')>0)
i_class = null;
if (i_class)
h += '<span class="'+i_class+'">' + i_line.replace(re_html, '<') + '</span>';
else
h += '<span>'+i_line.replace(re_html, '<')+'</span>';
}
pElement.setInnerHTML('server-logfile-content', '<pre><code>'+h/*i_request.responseText*/+'</pre></code>');
if (that.lockscroll === false)
pElement.scrollToBottom('server-logfile-content');
that.previous = i_request.responseText;
}
}
//*** RESOLVE PROMISE
resolve();
//*** CALL NEXT UPDATE
that.nextUpdate();
});
};
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
function onerror_libraryicon(img) {
img.src='/resources/html/images/32x32/music.png';
}
const pLibraryList = (window.pLibraryUpdateInstance)? new pLibraryUpdateInstance('LibraryList', 1000, 'server_libraries') : {};
pLibraryList.updateImpl = function(resolve, reject, that) {
if (pDocument.isShown(that.element)===false) {
pDocument.clearTimeout(that.id);
return;
}
var u = '/server?action=get-libraries&v='+Math.random();
pConsole.info(that, "GetLibraries: " + u);
pHTTPRequest.invoke({ url: u, onerror: that.onerror }).then(function(i_request) {
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
if (i_request.status == 200 && that.needsRefresh(i_request.responseText)) {
var i_obj = pJSON.parse(i_request.responseText);
pLibraryList.recents = i_obj.recents;
var h = '<div class="box">';
h += that.renderRefreshText();
h += '<div style="clear: both;"><!----></div>';
h += '<div class="listview-item">';
h += '<a class="image" href="javascript:pServer.openLibrary();" tabindex="-1">';
h += '<img class="image listview-image" src="/resources/html/images/32x32/folder_blue.png"/>';
h += '</a>';
h += '<a class="listview-text" href="javascript:pServer.openLibrary();">Open Library...</a>';
h += '</div>';
i_obj.libraries = pString.sortByName(i_obj.libraries);
for(var i=0 ; i<i_obj.libraries.length ; i++) {
var i_library = i_obj.libraries[i];
if (i_library.id) {
h += '<div class="listview-item">';
h += '<a class="image" href="'+url_prefix+i_library.id+'/library/" tabindex="-1">';
h += '<img class="image listview-image" src="'+i_library.thumbnail_uri+'" onError="onerror_libraryicon(this)"/>';
h += '</a>';
h += '<a class="listview-text" href="'+url_prefix+i_library.id+'/library/">'+pString.encodeHTML(i_library.name)+'</a>';
h += '</div>';
}
else {
h += '<div class="listview-item">';
if (i_library.state == "STOPPED")
h += '<img class="image listview-image" src="/resources/html/images/32x32/delete.png"/>';
else
h += '<img class="image listview-image" src="/resources/html/images/line-wait.gif"/>';
h += '<span class="listview-text">'+pString.encodeHTML(i_library.name)+'</span>';
h += '</div>';
}
}
h += '</div>';
pElement.setInnerHTML(that.element.id+'-content', h);
that.cache(i_request.responseText);
}
//*** RESOLVE PROMISE
resolve();
//*** CALL NEXT UPDATE
that.nextUpdate();
});
};
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
const pUserList = (window.pLibraryUpdateInstance)? new pLibraryUpdateInstance('UserList', 10000, 'users') : {};
pUserList.cols = [ 'Name', 'Login', 'Enabled', 'Administrator', 'Last Connection' ];
pUserList.updateImpl = function(resolve, reject, that) {
if (pDocument.isShown(that.element)===false) {
pDocument.clearTimeout(that.id);
return;
}
var u = '/server?action=get-users&v='+Math.random();
pConsole.info(that, "GetUsers: " + u);
pHTTPRequest.invoke({ url: u, onerror: that.onerror }).then(function(i_request) {
//if (i_request.status == 307 || i_request.status == 200)
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
if (i_request.status == 200 && that.needsRefresh(i_request.responseText)) {
var i_obj = pJSON.parse(i_request.responseText);
var h = '<div class="box">';
h += that.renderRefreshText();
h += '<table cellpadding="5" cellspacing="5" class="table-users" id="table-users"><tr><th/>';
that.cols.forEach(function(n) {
h += '<th><span class="link" title="Click here to sort this column" onclick="pTable.sortString('+sq+'table-users'+sq+', this.innerHTML, 0, true)">'+n+'</span></th>' });
h += '</tr>';
i_obj.users.forEach(function(u) {
h += '<tr>';
h += '<td><div class="icon icon-user user-'+u.name+'"><!----></div></td>';
h += '<td data-label="Name"><a class="link" href=\"/user?user='+u.name+'\" title="Go to this User page">'+pString.encodeHTML(u.fullname)+'</a></td>';
h += '<td data-label="Login">'+pString.encodeHTML(u.name)+'</td>';
if (u.visible != "true") h += '<td data-label="Enabled"><span class="warning">NO</span></td>'; else h += '<td data-label="Enabled"/>';
if (u.role_admin == "true") h += '<td data-label="Admin">YES</td>'; else h += '<td data-label="Admin"/>';
if (u.last_connection && !u.last_connection.startsWith("1970")) h += '<td data-label="Last Connection" data-sort=\"'+u.last_connection+'\">'+pHumanText.toDateTime(pDate.create(u.last_connection))+'</td>';
h += '</tr>';
});
h += '</table>';
h += '</div>';
pElement.setInnerHTML(that.element.id+'-content', h);
that.cache(i_request.responseText);
}
//*** RESOLVE PROMISE
resolve();
//*** CALL NEXT UPDATE
that.nextUpdate();
});
};
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
const pSessionList = (window.pLibraryUpdateInstance)? new pLibraryUpdateInstance('SessionList', 10000, 'user_sessions') : {};
pSessionList.bind("close", function(p_session_id) {
pHTTPRequest.sendDELETE("?action=delete-session&id="+p_session_id+"&v="+Math.random()).then(this.update);
});
pSessionList.view = function(p_session_id) {
pHTTPRequest.get('?action=get-session&id='+p_session_id, function(p_request) {
pConsole.info(p_request.responseText);
pDialog.dialogQuestion({ id: 'session-details', classes: 'dialog-main-menu', title: 'Session Details', options: [ 'ok', { id: 'details', sep: true, text: '<pre><samp>'+pJSON.pretty(p_request.responseText) + '</samp></pre>' }]});
});
};
pSessionList.cols = [ 'Name', 'Login', 'Connected', 'Expires', 'Device', 'Address' ];
pSessionList.updateImpl = function(resolve, reject, that) {
if (pDocument.isShown(that.element)===false) {
pDocument.clearTimeout(that.id);
return;
}
var u = '/server?action=get-sessions&v='+Math.random();
pConsole.info(that, "GetSessions: " + u);
pHTTPRequest.invoke({ url: u, onerror: that.onerror }).then(function(i_request) {
//if (i_request.status == 307 || i_request.status == 200)
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
if (i_request.status == 200 && that.needsRefresh(i_request.responseText)) {
var i_obj = pJSON.parse(i_request.responseText);
var h = '<div class="box">';
h += that.renderRefreshText();
h += '<table cellpadding="5" cellspacing="5" class="table-sessions" id="table-sessions"><tr><th/>';
that.cols.forEach(function(n) {
h += '<th><span class="link" title="Click here to sort this column" onclick="pTable.sortString('+sq+'table-sessions'+sq+', this.innerHTML, 0, true)">'+n+'</span></th>' });
h += '</tr>';
var i_oid = "'"+that.id+"'";
i_obj.sessions.forEach(function(s) {//for(var i=0 ; i<i_obj.sessions.length ; i++) {
//var s = i_obj.sessions[i];
var i_id = "'"+s.id+"'", t = pDevice.type(s.user_agent);
h += '<tr>';
h += '<td><div class="icon icon-user"><!----></div></td>';
h += '<td data-label="Name"><a class="link" href=\"/user?user='+s.name+'\" title="Go to this User page">'+pString.encodeHTML(s.fullname)+'</a></td>';
h += '<td data-label="Login">'+pString.encodeHTML(s.name)+'</td>';
h += '<td data-label="Connected">'+pHumanText.toDateTime(pDate.create(s.connected))+'</td>';
h += '<td data-label="Expires" data-sort=\"'+s.expires+'\">'+pHumanText.toDateTime(pDate.create(s.expires))+'</td>';
h += '<td data-label="Device">';
h += '<span class=\"device-'+t.toLowerCase()+'\">'+t+' - </span>';
h += '<span>'+pString.encodeHTML(s.user_agent)+'</span>';
h += '</td>';
h += '<td data-label="Address">'+pString.encodeHTML(s.address)+'</td>';
//h += '<td><a class="link" href="javascript:objects.getValue('+i_id+', null).view(\''+s.id+'\')">View this session</a></td>';
h += '<td><a class="link" href=\"javascript:objects.getValue('+i_oid+', null).close('+i_id+')\" title="Close this session">×</a></td>';
h += '</tr>';
});
h += '</table>';
h += '</div>';
pElement.setInnerHTML(that.element.id+'-content', h);
that.cache(i_request.responseText);
}
//*** RESOLVE PROMISE
resolve();
//*** CALL NEXT UPDATE
that.nextUpdate();
});
};
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
const pTranscodingList = (window.pLibraryUpdateInstance)? new pLibraryUpdateInstance('TranscodingList', 1000, 'transcodings') : {};
pTranscodingList.bind("remove", function(p_id) {
pHTTPRequest.sendDELETE("?action=remove-transcoding&id="+p_id+"&v="+Math.random()).then(this.update);
});
pTranscodingList.status = function(s) {
return s? s.split(' ').filter(function(s) { return s.startsWith('Start') || s.startsWith('frame=') || s.startsWith('fps=') || s.startsWith('out_time=') || s.startsWith('speed=')}).join(', ') : '';
};
pTranscodingList.updateImpl = function(resolve, reject, that) {
if (pDocument.isShown(that.element)===false) {
pDocument.clearTimeout(that.id);
return;
}
var u = '/server?action=get-transcodings&v='+Math.random();
pConsole.info(that, "GetTranscodings: " + u);
pHTTPRequest.invoke({ url: u, onerror: that.onerror }).then(function(i_request) {
//if (i_request.status == 307 || i_request.status == 200)
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
if (i_request.status == 200 && that.needsRefresh(i_request.responseText)) {
var i_obj = pJSON.parse(i_request.responseText);
var h = '';
h += '<div class="box">';
h += that.renderRefreshText();
h += '<div>';
//h += 'You can configure transcoding by selecting <a href="javascript:void(doShow(\'server-settings\'))" xtarget="_blank">Server Settings</a>...';
h += '<p>Transcoded files or files being currently transcoded (current size: '+pHumanText.toByteSize(i_obj.bytes)+', max size: '+pHumanText.toByteSize(i_obj.max_bytes)+'):</div>';
h += '<table cellpadding="5" cellspacing="5" class="table-transcodings" id="table-transcodings"><tr><th/>';
[ 'File', 'State', 'Status', 'Started', 'Ended' ].forEach(function(n) {
h += '<th><span class="link" title="Click here to sort this column" onclick="pTable.sortString('+sq+'table-transcodings'+sq+', this.innerHTML, 0, true)">'+n+'</span></th>';
});
h += '</tr>';
var i_oid = "'"+that.id+"'";
i_obj.transcoders.forEach(function(s) {
var i_id = "'"+s.id+"'";
h += '<tr title="'+s.file+'">';
h += '<td>';
h += '<img class="image toolbar-icon" src="/resources/html/images/16x16/microformats.png"/>';
h += '</td>';
h += '<td data-label="File">.../' + pString.encodeHTML(pString.basename(pString.dirname(s.file))) + '/' + pString.encodeHTML(pString.basename(s.file)) + '</td>';
//h += '<td></td>';// + s.uri + '</td>';
h += '<td data-label="State">' + pString.encodeHTML(s.state) + '</td>';
h += '<td data-label="Status">' + pString.encodeHTML(pTranscodingList.status(s.status)) + '</td>';
h += '<td data-label="Started" data-sort="'+s.start+'">' + ((s.start)? pHumanText.toDateTime(pDate.create(s.start)) : '') + '</td>';
h += '<td data-label="Ended" data-sort="'+s.end+'">' + ((s.end)? pHumanText.toDateTime(pDate.create(s.end)) : '') + '</td>';
h += '<td><span class="link" onclick="objects.getValue('+i_oid+', null).remove('+i_id+')" title="Delete that trancoding data">×</span></td>';
h += '</tr>';
});
h += '</table>';
h += '</div>';
pElement.setInnerHTML(that.element.id+'-content', h);
that.cache(i_request.responseText);
}
//*** RESOLVE PROMISE
resolve();
//*** CALL NEXT UPDATE
that.nextUpdate();
});
};
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
window.pStaticTranscodingList = (window.pLibraryUpdateInstance)? new pLibraryUpdateInstance('StaticTranscodingList', 1000, 'static-transcodings') : {};
pStaticTranscodingList.bind("remove", function(p_id) {
pHTTPRequest.sendDELETE("?action=remove-static-transcoding&id="+p_id+"&v="+Math.random()).then(this.update);
});
pStaticTranscodingList.updateImpl = function(resolve, reject, that) {
if (pDocument.isShown(that.element)===false) {
pDocument.clearTimeout(that.id);
return;
}
var u = '/server?action=get-static-transcodings&v='+Math.random();
pConsole.info(that, "GetStaticTranscodings: " + u);
pHTTPRequest.invoke({ url: u, onerror: that.onerror }).then(function(i_request) {
//if (i_request.status == 307 || i_request.status == 200)
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
if (i_request.status == 200 && that.needsRefresh(i_request.responseText)) {
var i_obj = pJSON.parse(i_request.responseText);
var h = '<div class="box">';
h += that.renderRefreshText();
h += '<div>';
//h += 'You can configure transcoding by selecting <a href="javascript:doShow(\'server-settings\')" xtarget="_blank">Server Settings</a>...';
h += '<p>Transcoded files or files being currently transcoded (current size: '+pHumanText.toByteSize(i_obj.bytes)+'):</div>';
h += '<table cellpadding="5" cellspacing="5" class="table-transcodings" id="table-transcodings"><tr><th/>';
[ 'File', 'State', 'Status', 'Started', 'Ended' ].forEach(function(n) {
h += '<th><span class="link" title="Click here to sort this column" onclick="pTable.sortString('+sq+'table-transcodings'+sq+', this.innerHTML, 0, true)">'+n+'</span></th>';
});
h += '</tr>';
var i_oid = "'"+that.id+"'";
i_obj.transcoders.forEach(function(s) {
var i_id = "'"+s.id+"'";
h += '<tr title="'+s.file+'">';
h += '<td>';
h += '<img class="image toolbar-icon" src="/resources/html/images/16x16/microformats.png"/>';
h += '</td>';
h += '<td data-label="File">.../' + pString.encodeHTML(pString.basename(pString.dirname(s.file))) + '/' + pString.encodeHTML(pString.basename(s.file)) + '</td>';
//h += '<td></td>';// + s.uri + '</td>';
h += '<td data-label="State">' + pString.encodeHTML(s.state) + '</td>';
h += '<td data-label="Status">' + pString.encodeHTML(pTranscodingList.status(s.status)) + '</td>';
h += '<td data-label="Started" data-sort="'+s.start+'">' + ((s.start)? pHumanText.toDateTime(pDate.create(s.start)) : '') + '</td>';
h += '<td data-label="Ended" data-sort="'+s.end+'">' + ((s.end)? pHumanText.toDateTime(pDate.create(s.end)) : '') + '</td>';
h += '<td><span class="link" onclick="objects.getValue('+i_oid+', null).remove('+i_id+')" title="Delete this trancoding data">×</span></td>';
h += '</tr>';
});
h += '</table>';
h += '</div>';
pElement.setInnerHTML(that.element.id+'-content', h);
that.cache(i_request.responseText);
}
//*** RESOLVE PROMISE
resolve();
//*** CALL NEXT UPDATE
that.nextUpdate();
});
};
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
const pMediaConversionList = new pLibraryUpdateInstance('MediaConversionList', 1000, 'media-conversions');
pMediaConversionList.url = window.location.pathname;
pMediaConversionList.updateImpl = function(resolve, reject, that) {
if (pDocument.isShown(that.element)===false) {
pDocument.clearTimeout(that.id);
return;
}
var u = that.url+'?action=get-media-conversions&v='+Math.random();
pConsole.info(that, "GetMediaConversions: " + u);
pHTTPRequest.invoke({ url: u, onerror: that.onerror }).then(function(i_request) {
//handle errors
if (pROSE.handleHTTPResponse(i_request) === false)
return false;
if (i_request.status == 200 && that.needsRefresh(i_request.responseText)) {
var o = pJSON.parse(i_request.responseText);
var h = '<div class="box">';
h += that.renderRefreshText();
h += '<div>Media conversions currently executed:</div>';
h += '<table cellpadding="5" cellspacing="5" class="table-library-jobs"><tr><th/>';
[ 'Task', 'State', 'Started', 'Ended' ].forEach(function(n) {
h += '<th style="text-align: left;"><a class="link" title="Click here to sort this column" href="javascript:sortTableString('+sq+n+sq+')">'+n+'</a></th>';
});
h += '</tr>';
o.threads.forEach(function(t) {
h += '<tr style="text-align: left;">';
h += '<td>';
if (t.finished)
h += '<img class="image toolbar-icon" src="/resources/html/images/16x16/microformats.png"/>';
else if (t.executed)
h += '<div class="icon icon-task-running"><!----></div>';
else
h += '<div class="icon icon-task-waiting"><!----></div>';
h += '</td>';
h += '<td data-label="Task">'+pString.encodeHTML(t.title)+pString.encodeHTML(pString.v(t.status)? '<br>'+t.status : '')+'</td>';
h += '<td data-label="State">'+(t.finished? 'COMPLETED' : (t.executed? 'RUNNING...':'WAITING...'))+'</td>';
h += '<td data-label="Started" data-sort=\"'+t.started+'\">'+(t.started? pHumanText.toDateTime(pDate.create(t.started)):'')+'</td>';
h += '<td data-label="Ended" data-sort="'+t.ended+'">' + ((t.ended)? pHumanText.toDateTime(pDate.create(t.ended)) : '') + '</td>';
h += '</tr>';
});
h += '</table></div>';
pElement.setInnerHTML(that.element.id+'-content', h);
that.cache(i_request.responseText);
}
//*** RESOLVE PROMISE
resolve();
//*** CALL NEXT UPDATE
that.nextUpdate();
});
};
/******************************************************************************/
/*** END OF FILE ************************************************************/
/******************************************************************************/