Also applied the new selected info structure for ServerEntity and ChannelEntity

canary
WolverinDEV 2018-06-20 21:05:35 +02:00
parent 6bb0179958
commit 31d8b7a56c
12 changed files with 387 additions and 291 deletions

10
css/frame/SelectInfo.css Normal file
View File

@ -0,0 +1,10 @@
.select_info_table { }
.select_info_table tr { }
.select_info_table tr td {
}
.select_info_table tr td:nth-child(1) {
font-weight: bold;
padding-right: 5px;
min-width: 20%;
}

View File

@ -103,11 +103,6 @@
flex-direction: column;
}
.info_key {
font-weight: bold;
padding-right: 5px;
}
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */

View File

@ -31,6 +31,7 @@
<link rel="stylesheet" href="css/modals.css" type="text/css">
<link rel="stylesheet" href="css/loader.css" type="text/css">
<link rel="stylesheet" href="css/music/info_plate.css" type="text/css">
<link rel="stylesheet" href="css/frame/SelectInfo.css" type="text/css">
<!-- https://localhost:9987/?forward_url=http%3A%2F%2Flocalhost%3A63344%2FWeb-Client%2Findex.php%3F_ijt%3D82b1uhmnh0a5l1n35nnjps5eid%26loader_ignore_age%3D1%26connect_default_host%3Dlocalhost%26default_connect_type%3Dforum%26default_connect_url%3Dtrue%26default_connect_type%3Dteamspeak%26default_connect_url%3Dlocalhost%253A9987 -->
<!-- PHP generated properies -->

View File

@ -227,7 +227,7 @@ class FileManager {
transfer.remotePort = json["port"];
transfer.remoteHost = (json["ip"] ? json["ip"] : "").replace(/,/g, "");
if(!transfer.remoteHost || transfer.remoteHost == '0.0.0.0' || transfer.remoteHost == '127.168.0.0')
transfer.remoteHost = this.handle.serverConnection._remoteHost;
transfer.remoteHost = this.handle.serverConnection._remote_address.host;
(transfer["_promiseCallback"] as (val: DownloadFileTransfer) => void)(transfer);
this.pendingDownloadTransfers.remove(transfer);

View File

@ -91,8 +91,8 @@ class TSClient {
port = 9987;
}
console.log("Start connection to " + host + ":" + port);
this.channelTree.initialiseHead(addr);
this.serverConnection.startConnection(host, port, new HandshakeHandler(identity, name));
this.channelTree.initialiseHead(addr, {host, port});
this.serverConnection.startConnection({host, port}, new HandshakeHandler(identity, name));
}
@ -145,9 +145,9 @@ class TSClient {
callback += "&default_connect_type=teamspeak";
break;
}
callback += "&default_connect_url=" + encodeURIComponent(this.serverConnection._remoteHost + ":" + this.serverConnection._remotePort);
callback += "&default_connect_url=" + encodeURIComponent(this.serverConnection._remote_address.host + ":" + this.serverConnection._remote_address.port);
return "https://" + this.serverConnection._remoteHost + ":" + this.serverConnection._remotePort + "/?forward_url=" + encodeURIComponent(callback);
return "https://" + this.serverConnection._remote_address.host + ":" + this.serverConnection._remote_address.port + "/?forward_url=" + encodeURIComponent(callback);
}
handleDisconnect(type: DisconnectReason, data: any = {}) {

View File

@ -31,8 +31,7 @@ class ReturnListener<T> {
class ServerConnection {
_client: TSClient;
_remoteHost: string;
_remotePort: number;
_remote_address: ServerAddress;
_socket: WebSocket;
_connectionState: ConnectionState = ConnectionState.UNCONNECTED;
_handshakeHandler: HandshakeHandler;
@ -62,19 +61,18 @@ class ServerConnection {
return (this._retCodeIdx++).toString();
}
startConnection(host : string, port : number, handshake: HandshakeHandler, timeout: number = 1000) {
startConnection(address : ServerAddress, handshake: HandshakeHandler, timeout: number = 1000) {
if(this._connectTimeoutHandler) {
clearTimeout(this._connectTimeoutHandler);
this._connectTimeoutHandler = null;
this.disconnect();
}
this.updateConnectionState(ConnectionState.CONNECTING);
this._remoteHost = host;
this._remotePort = port;
this._remote_address = address;
this._handshakeHandler = handshake;
this._handshakeHandler.setConnection(this);
this._connected = false;
chat.serverChat().appendMessage("Connecting to " + host + ":" + port);
chat.serverChat().appendMessage("Connecting to " + address.host + ":" + address.port);
const self = this;
try {
@ -83,7 +81,7 @@ class ServerConnection {
this._client.handleDisconnect(DisconnectReason.CONNECT_FAILURE);
}, timeout);
let sockCpy;
this._socket = (sockCpy = new WebSocket('wss:' + this._remoteHost + ":" + this._remotePort));
this._socket = (sockCpy = new WebSocket('wss:' + address.host + ":" + address.port));
clearTimeout(this._connectTimeoutHandler);
this._connectTimeoutHandler = null;
if(this._socket != sockCpy) return; //Connect timeouted
@ -375,11 +373,19 @@ class ConnectionCommandHandler {
this.connection._client.clientId = parseInt(json["aclid"]);
this.connection._client.getClient().updateVariables({key: "client_nickname", value: json["acn"]});
let updates: {
key: string,
value: string
}[] = [];
for(let key in json) {
if(key === "aclid") continue;
if(key === "acn") continue;
this.connection._client.channelTree.server.updateProperty(key, json[key]);
updates.push({key: key, value: json[key]});
}
this.connection._client.channelTree.server.updateVariables(...updates);
chat.serverChat().name = this.connection._client.channelTree.server.properties["virtualserver_name"];
chat.serverChat().appendMessage("Connected as {0}", true, this.connection._client.getClient().createChatTag(true));
globalClient.onConnected();
@ -712,27 +718,39 @@ class ConnectionCommandHandler {
handleNotifyServerEdited(json) {
json = json[0];
let updates: {
key: string,
value: string
}[] = [];
for(let key in json) {
if(key === "invokerid") continue;
if(key === "invokername") continue;
if(key === "invokeruid") continue;
if(key === "reasonid") continue;
this.connection._client.channelTree.server.updateProperty(key, json[key]);
updates.push({key: key, value: json[key]});
}
this.connection._client.channelTree.server.updateVariables(...updates);
if(this.connection._client.selectInfo.currentSelected == this.connection._client.channelTree.server)
this.connection._client.selectInfo.update();
}
handleNotifyServerUpdated(json) {
json = json[0];
let updates: {
key: string,
value: string
}[] = [];
for(let key in json) {
if(key === "invokerid") continue;
if(key === "invokername") continue;
if(key === "invokeruid") continue;
if(key === "reasonid") continue;
this.connection._client.channelTree.server.updateProperty(key, json[key]);
updates.push({key: key, value: json[key]});
}
this.connection._client.channelTree.server.updateVariables(...updates);
let info = this.connection._client.selectInfo;
if(info.currentSelected instanceof ServerEntry)
info.update();

View File

@ -1,6 +1,7 @@
enum LogCategory {
CHANNEL,
CLIENT,
SERVER,
PERMISSIONS,
GENERAL,
NETWORKING
@ -18,6 +19,7 @@ namespace log {
let category_mapping = new Map<number, string>([
[LogCategory.CHANNEL, "Channel "],
[LogCategory.CLIENT, "Client "],
[LogCategory.SERVER, "Server "],
[LogCategory.PERMISSIONS, "Permission "],
[LogCategory.GENERAL, "General "],
[LogCategory.NETWORKING, "Network "]

View File

@ -7,10 +7,13 @@ interface Array<T> {
interface JQuery {
tmpl(values?: any) : JQuery;
render(values?: any) : string;
renderTag(values?: any) : JQuery;
}
interface JQueryStatic<TElement extends Node = HTMLElement> {
spawn<K extends keyof HTMLElementTagNameMap>(tagName: K): JQuery<HTMLElementTagNameMap[K]>;
views: any;
}
@ -51,12 +54,11 @@ if(typeof ($) !== "undefined") {
return $(document.createElement(tagName));
}
}
if(!$.prototype.tmpl) {
$.prototype.tmpl = function (values?: any) : JQuery {
return this.render(values);
if(!$.prototype.renderTag) {
$.prototype.renderTag = function (values?: any) : JQuery {
return $(this.render(values));
}
}
}
if (!String.prototype.format) {

View File

@ -5,21 +5,21 @@ abstract class InfoManagerBase {
private intervals: number[] = [];
protected resetTimers() {
for(let interval of this.intervals)
clearInterval(interval);
for(let timer of this.timers)
clearTimeout(timer);
}
protected resetIntervals() {
for(let timer of this.timers)
clearTimeout(timer);
for(let interval of this.intervals)
clearInterval(interval);
}
protected registerTimer(timer: NodeJS.Timer) {
this.timers.push(timer);
}
protected registerInterval(interval: number) {
this.intervals.push(interval);
protected registerInterval<T extends number | NodeJS.Timer>(interval: T) {
this.intervals.push(interval as number);
}
abstract available<V>(object: V) : boolean;
@ -41,9 +41,6 @@ class InfoBar {
private current_selected?: ServerEntry | ChannelEntry | ClientEntry;
private _htmlTag: JQuery<HTMLElement>;
private timers: NodeJS.Timer[] = [];
private intervals: number[] = [];
private current_manager: InfoManagerBase = undefined;
private managers: InfoManagerBase[] = [];
@ -52,31 +49,30 @@ class InfoBar {
this._htmlTag = htmlTag;
this.managers.push(new ClientInfoManager());
}
this.managers.push(new ChannelInfoManager());
this.managers.push(new ServerInfoManager());
//TODO music client
/*
this._htmlTag.append("Im a music bot!");
let frame = $("#tmpl_music_frame" + (this.current_selected.properties.music_track_id == 0 ? "_empty" : "")).tmpl({
thumbnail: "img/loading_image.svg"
}).css("align-self", "center");
private createInfoTable(infos: any) : JQuery<HTMLElement> {
let table = $.spawn("table");
if(this.current_selected.properties.music_track_id == 0) {
for(let key in infos) {
console.log("Display info " + key);
let entry = $.spawn("tr");
entry.append($.spawn("td").addClass("info_key").html(key + ":"));
let value = $.spawn("td");
console.log(infos[key]);
console.log( MessageHelper.formatElement(infos[key]));
MessageHelper.formatElement(infos[key]).forEach(e => e.appendTo(value));
entry.append(value);
table.append(entry);
}
} else {
return table;
}
this._htmlTag.append(frame);
*/
}
setCurrentSelected<T extends ServerEntry | ChannelEntry | ClientEntry | undefined>(entry: T) {
if(this.current_selected == entry) return;
if(this.current_manager) {
this.current_manager.finalizeFrame.call(this.current_manager, this.current_selected, this._htmlTag);
(this.current_manager as InfoManager<undefined>).finalizeFrame.call(this.current_manager, this.current_selected, this._htmlTag);
this.current_manager = null;
this.current_selected = null;
}
@ -90,10 +86,9 @@ class InfoBar {
}
}
console.log("Got info manager: %o", this.current_manager);
if(this.current_manager) {
this.current_manager.createFrame.call(this.current_manager, this.current_selected, this._htmlTag);
} else this.buildBar(); //FIXME Remove that this is just for now (because not all types are implemented)
console.log("Using info manager: %o", this.current_manager);
if(this.current_manager)
(this.current_manager as InfoManager<undefined>).createFrame.call(this.current_manager, this.current_selected, this._htmlTag);
}
get currentSelected() {
@ -102,204 +97,7 @@ class InfoBar {
update(){
if(this.current_manager && this.current_selected)
this.current_manager.updateFrame.call(this.current_manager, this.current_selected, this._htmlTag);
}
private updateServerTimings() {
this._htmlTag.find(".uptime").text(formatDate((this.current_selected as ServerEntry).calculateUptime()));
}
private updateClientTimings() {
this._htmlTag.find(".online").text(formatDate((this.current_selected as ClientEntry).calculateOnlineTime()));
}
private buildBar() {
this._htmlTag.empty();
if(!this.current_selected) return;
if(this.current_selected instanceof ServerEntry) {
if(this.current_selected.shouldUpdateProperties()) this.current_selected.updateProperties();
let version = this.current_selected.properties.virtualserver_version;
if(version.startsWith("TeaSpeak ")) version = version.substr("TeaSpeak ".length);
this._htmlTag.append(this.createInfoTable({
"Name": this.current_selected.properties.virtualserver_name,
"Address": "unknown",
"Type": "TeaSpeak",
"Version": version + " on " + this.current_selected.properties.virtualserver_platform,
"Uptime": "<a class='uptime'>" + formatDate(this.current_selected.calculateUptime()) + "</a>",
"Current Channels": this.current_selected.properties.virtualserver_channelsonline,
"Current Clients": this.current_selected.properties.virtualserver_clientsonline,
"Current Queries": this.current_selected.properties.virtualserver_queryclientsonline
}));
this._htmlTag.append($.spawn("div").css("height", "100%"));
let requestUpdate = $.spawn("button");
requestUpdate.css("min-height", "16px");
requestUpdate.css("bottom", 0);
requestUpdate.text("update info");
if(this.current_selected.shouldUpdateProperties())
requestUpdate.css("color", "green");
else {
requestUpdate.attr("disabled", "true");
requestUpdate.css("color", "red");
}
this._htmlTag.append(requestUpdate);
const _server : ServerEntry = this.current_selected;
const _this = this;
requestUpdate.click(function () {
_server.updateProperties();
_this.buildBar();
});
this.timers.push(setTimeout(function () {
requestUpdate.css("color", "green");
requestUpdate.removeAttr("disabled");
}, _server.nextInfoRequest - new Date().getTime()));
this.intervals.push(setInterval(this.updateServerTimings.bind(this),1000));
} else if(this.current_selected instanceof ChannelEntry) {
let props = this.current_selected.properties;
this._htmlTag.append(this.createInfoTable({
"Name": this.current_selected.createChatTag(),
"Topic": this.current_selected.properties.channel_topic,
"Codec": this.current_selected.properties.channel_codec,
"Codec Quality": this.current_selected.properties.channel_codec_quality,
"Type": ChannelType.normalize(this.current_selected.channelType()),
"Current clients": this.current_selected.channelTree.clientsByChannel(this.current_selected).length + " / " + (props.channel_maxclients == -1 ? "Unlimited" : props.channel_maxclients),
"Subscription Status": "unknown",
"Voice Data Encryption": "unknown"
}));
} else if(this.current_selected instanceof MusicClientEntry) {
this._htmlTag.append("Im a music bot!");
let frame = $("#tmpl_music_frame" + (this.current_selected.properties.music_track_id == 0 ? "_empty" : "")).tmpl({
thumbnail: "img/loading_image.svg"
}).css("align-self", "center");
if(this.current_selected.properties.music_track_id == 0) {
} else {
}
this._htmlTag.append(frame);
//TODO
} else if(this.current_selected instanceof ClientEntry) {
this.current_selected.updateClientVariables();
let version: string = this.current_selected.properties.client_version;
if(!version) version = "";
let infos = {
"Name": this.current_selected.createChatTag(),
"Description": this.current_selected.properties.client_description,
"Version": MessageHelper.formatMessage("{0} on {1}", $.spawn("a").attr("title", version).text(version.split(" ")[0]), this.current_selected.properties.client_platform),
"Online since": $.spawn("a").addClass("online").text(formatDate(this.current_selected.calculateOnlineTime())),
"Volume": this.current_selected.audioController.volume * 100 + " %"
};
if(this.current_selected.properties.client_teaforum_id > 0) {
infos["TeaSpeak Account"] = $.spawn("a")
.attr("href", "//forum.teaspeak.de/index.php?members/" + this.current_selected.properties.client_teaforum_id)
.attr("target", "_blank")
.text(this.current_selected.properties.client_teaforum_id);
}
this._htmlTag.append(this.createInfoTable(infos));
{
let serverGroups = $.spawn("div");
serverGroups
.css("display", "flex")
.css("flex-direction", "column");
let header = $.spawn("div");
header
.css("display", "flex")
.css("margin-top", "5px")
.css("align-items", "center");
$.spawn("div").addClass("icon client-permission_server_groups").appendTo(header);
$.spawn("div").text("Server groups:").css("margin-left", "3px").css("font-weight", "bold").appendTo(header);
header.appendTo(serverGroups);
for(let groupId of this.current_selected.assignedServerGroupIds()) {
let group = this.handle.groups.serverGroup(groupId);
if(!group) continue;
let groupTag = $.spawn("div");
groupTag
.css("display", "flex")
.css("margin-top", "1px")
.css("margin-left", "10px")
.css("align-items", "center");
this.handle.fileManager.icons.generateTag(group.properties.iconid).appendTo(groupTag);
$.spawn("div").text(group.name).css("margin-left", "3px").appendTo(groupTag);
groupTag.appendTo(serverGroups);
}
this._htmlTag.append(serverGroups);
}
{
let channelGroup = $.spawn("div");
channelGroup
.css("display", "flex")
.css("flex-direction", "column")
.css("margin-bottom", "20px");
let header = $.spawn("div");
header
.css("display", "flex")
.css("margin-top", "10px")
.css("align-items", "center");
$.spawn("div").addClass("icon client-permission_channel").appendTo(header);
$.spawn("div").text("Channel group:").css("margin-left", "3px").css("font-weight", "bold").appendTo(header);
header.appendTo(channelGroup);
let group = this.handle.groups.channelGroup(this.current_selected.assignedChannelGroup());
if(group) {
let groupTag = $.spawn("div");
groupTag
.css("display", "flex")
.css("margin-top", "1px")
.css("margin-left", "10px")
.css("align-items", "center");
this.handle.fileManager.icons.generateTag(group.properties.iconid).appendTo(groupTag);
$.spawn("div").text(group.name)
.css("margin-left", "3px").appendTo(groupTag);
groupTag.appendTo(channelGroup);
}
this._htmlTag.append(channelGroup);
}
{
if(this.current_selected.properties.client_flag_avatar.length > 0)
this.handle.fileManager.avatars.generateTag(this.current_selected)
.css("max-height", "90%")
.css("max-width", "100%").appendTo(this._htmlTag);
}
{
let spawnTag = (type: string, description: string) : JQuery => {
return $.spawn("div").css("display", "inline-flex")
.append($.spawn("div").addClass("icon_x32 client-" + type).css("margin-right", "5px"))
.append($.spawn("a").text(description).css("align-self", "center"));
};
if(!this.current_selected.properties.client_output_hardware)
spawnTag("hardware_output_muted", "Speakers/Headphones disabled").appendTo(this._htmlTag);
if(!this.current_selected.properties.client_input_hardware)
spawnTag("hardware_input_muted", "Microphone disabled").appendTo(this._htmlTag);
if(this.current_selected.properties.client_output_muted)
spawnTag("output_muted", "Speakers/Headphones Muted").appendTo(this._htmlTag);
if(this.current_selected.properties.client_input_muted)
spawnTag("input_muted", "Microphone Muted").appendTo(this._htmlTag);
}
this.intervals.push(setInterval(this.updateClientTimings.bind(this),1000));
}
(this.current_manager as InfoManager<undefined>).updateFrame.call(this.current_manager, this.current_selected, this._htmlTag);
}
}
@ -314,13 +112,10 @@ class ClientInfoManager extends InfoManager<ClientEntry> {
}
updateFrame(client: ClientEntry, html_tag: JQuery<HTMLElement>) {
this.resetIntervals();
html_tag.empty();
let properties: any = {};
let version: string = client.properties.client_version;
if(!version) version = "";
properties["client_name"] = client.createChatTag()[0];
properties["client_onlinetime"] = formatDate(client.calculateOnlineTime());
properties["sound_volume"] = client.audioController.volume * 100;
@ -355,9 +150,100 @@ class ClientInfoManager extends InfoManager<ClientEntry> {
.text(client.properties.client_teaforum_id);
}
let rendered = $($("#tmpl_selected_client").render([properties]));
let rendered = $("#tmpl_selected_client").renderTag([properties]);
rendered.find("node").each((index, element) => { $(element).replaceWith(properties[$(element).attr("key")]); });
html_tag.append(rendered);
console.log(properties);
this.registerInterval(setInterval(() => {
html_tag.find(".update_onlinetime").text(formatDate(client.calculateOnlineTime()));
}, 1000));
}
}
class ServerInfoManager extends InfoManager<ServerEntry> {
createFrame(server: ServerEntry, html_tag: JQuery<HTMLElement>) {
if(server.shouldUpdateProperties()) server.updateProperties();
this.updateFrame(server, html_tag);
}
updateFrame(server: ServerEntry, html_tag: JQuery<HTMLElement>) {
this.resetIntervals();
html_tag.empty();
let properties: any = {};
properties["server_name"] = $.spawn("a").text(server.properties.virtualserver_name);
properties["server_onlinetime"] = formatDate(server.calculateUptime());
properties["server_address"] = server.remote_address.host + ":" + server.remote_address.port;
for(let key in server.properties)
properties["property_" + key] = server.properties[key];
let rendered = $("#tmpl_selected_server").renderTag([properties]);
rendered.find("node").each((index, element) => { $(element).replaceWith(properties[$(element).attr("key")]); });
html_tag.append(rendered);
this.registerInterval(setInterval(() => {
html_tag.find(".update_onlinetime").text(formatDate(server.calculateUptime()));
}, 1000));
//TODO update button
/*
let requestUpdate = $.spawn("button");
requestUpdate.css("min-height", "16px");
requestUpdate.css("bottom", 0);
requestUpdate.text("update info");
if(this.current_selected.shouldUpdateProperties())
requestUpdate.css("color", "green");
else {
requestUpdate.attr("disabled", "true");
requestUpdate.css("color", "red");
}
this._htmlTag.append(requestUpdate);
const _server : ServerEntry = this.current_selected;
const _this = this;
requestUpdate.click(function () {
_server.updateProperties();
_this.buildBar();
});
this.timers.push(setTimeout(function () {
requestUpdate.css("color", "green");
requestUpdate.removeAttr("disabled");
}, _server.nextInfoRequest - new Date().getTime()));
*/
}
available<V>(object: V): boolean {
return typeof object == "object" && object instanceof ServerEntry;
}
}
class ChannelInfoManager extends InfoManager<ChannelEntry> {
createFrame(channel: ChannelEntry, html_tag: JQuery<HTMLElement>) {
this.updateFrame(channel, html_tag);
}
updateFrame(channel: ChannelEntry, html_tag: JQuery<HTMLElement>) {
this.resetIntervals();
html_tag.empty();
let properties: any = {};
properties["channel_name"] = channel.createChatTag();
properties["channel_type"] = ChannelType.normalize(channel.channelType());
properties["channel_clients"] = channel.channelTree.clientsByChannel(channel).length;
properties["channel_subscribed"] = true; //TODO
for(let key in channel.properties)
properties["property_" + key] = channel.properties[key];
let rendered = $("#tmpl_selected_channel").renderTag([properties]);
rendered.find("node").each((index, element) => { $(element).replaceWith(properties[$(element).attr("key")]); });
html_tag.append(rendered);
}
available<V>(object: V): boolean {
return typeof object == "object" && object instanceof ChannelEntry;
}
}

View File

@ -1,27 +1,37 @@
/// <reference path="channel.ts" />
class ServerEntry {
channelTree: ChannelTree;
properties: any = {
virtualserver_name: "",
virtualserver_icon_id: 0,
virtualserver_version: "unknown",
virtualserver_platform: "unknown",
virtualserver_unique_identifier: "",
class ServerProperties {
virtualserver_name: string = "";
virtualserver_icon_id: number = 0;
virtualserver_version: string = "unknown";
virtualserver_platform: string = "unknown";
virtualserver_unique_identifier: string = "";
virtualserver_clientsonline: 0,
virtualserver_queryclientsonline: 0,
virtualserver_channelsonline: 0,
virtualserver_uptime: 0,
virtualserver_maxclients: 0
};
virtualserver_clientsonline: number = 0;
virtualserver_queryclientsonline: number = 0;
virtualserver_channelsonline: number = 0;
virtualserver_uptime: number = 0;
virtualserver_maxclients: number = 0
}
interface ServerAddress {
host: string;
port: number;
}
class ServerEntry {
remote_address: ServerAddress;
channelTree: ChannelTree;
properties: ServerProperties;
lastInfoRequest: number = 0;
nextInfoRequest: number = 0;
private _htmlTag: JQuery<HTMLElement>;
constructor(tree, name) {
constructor(tree, name, address: ServerAddress) {
this.properties = new ServerProperties();
this.channelTree = tree;
this.remote_address = address;
this.properties.virtualserver_name = name;
}
@ -70,15 +80,26 @@ class ServerEntry {
);
}
updateProperty(key, value) : void {
console.log("Updating property " + key + " => '" + value + "' for the server");
this.properties[key] = value;
if(key == "virtualserver_name") {
this.htmlTag.find(".name").text(value);
} else if(key == "virtualserver_icon_id") {
if(this.channelTree.client.fileManager && this.channelTree.client.fileManager.icons)
this.htmlTag.find(".icon_property").replaceWith(this.channelTree.client.fileManager.icons.generateTag(this.properties.virtualserver_icon_id).addClass("icon_property"));
updateVariables(...variables: {key: string, value: string}[]) {
let group = log.group(log.LogType.DEBUG, LogCategory.SERVER, "Update properties (%i)", variables.length);
for(let variable of variables) {
if(typeof(this.properties[variable.key]) === "boolean")
this.properties[variable.key] = variable.value == "true" || variable.value == "1";
else if(typeof (this.properties[variable.key]) === "number")
this.properties[variable.key] = parseInt(variable.value);
else
this.properties[variable.key] = variable.value;
group.log("Updating server " + this.properties.virtualserver_name + ". Key " + variable.key + " Value: '" + variable.value + "' (" + typeof (this.properties[variable.key]) + ")");
if(variable.key == "virtualserver_name") {
this.htmlTag.find(".name").text(variable.value);
} else if(variable.key == "virtualserver_icon_id") {
if(this.channelTree.client.fileManager && this.channelTree.client.fileManager.icons)
this.htmlTag.find(".icon_property").replaceWith(this.channelTree.client.fileManager.icons.generateTag(this.properties.virtualserver_icon_id).addClass("icon_property"));
}
}
group.end();
}
updateProperties() {
@ -92,7 +113,7 @@ class ServerEntry {
}
calculateUptime() : number {
if(this.properties.virtualserver_uptime == 0 || this.lastInfoRequest == 0) return Number.parseInt(this.properties.virtualserver_uptime);
return Number.parseInt(this.properties.virtualserver_uptime) + (new Date().getTime() - this.lastInfoRequest) / 1000;
if(this.properties.virtualserver_uptime == 0 || this.lastInfoRequest == 0) return this.properties.virtualserver_uptime;
return this.properties.virtualserver_uptime + (new Date().getTime() - this.lastInfoRequest) / 1000;
}
}

View File

@ -48,8 +48,8 @@ class ChannelTree {
);
}
initialiseHead(serverName: string) {
this.server = new ServerEntry(this, serverName);
initialiseHead(serverName: string, address: ServerAddress) {
this.server = new ServerEntry(this, serverName, address);
this.server.htmlTag.appendTo(this.htmlTree);
this.server.initializeListener();
}

View File

@ -303,35 +303,55 @@
</div>
</template>
<!--
let spawnTag = (type: string, description: string) : JQuery => {
return $.spawn("div").css("display", "inline-flex")
.append($.spawn("div").addClass("icon_x32 client-" + type).css("margin-right", "5px"))
.append($.spawn("a").text(description).css("align-self", "center"));
};
if(!this.current_selected.properties.client_output_hardware)
spawnTag("hardware_output_muted", "Speakers/Headphones disabled").appendTo(this._htmlTag);
if(!this.current_selected.properties.client_input_hardware)
spawnTag("hardware_input_muted", "Microphone disabled").appendTo(this._htmlTag);
if(this.current_selected.properties.client_output_muted)
spawnTag("output_muted", "Speakers/Headphones Muted").appendTo(this._htmlTag);
if(this.current_selected.properties.client_input_muted)
spawnTag("input_muted", "Microphone Muted").appendTo(this._htmlTag);
-->
<script id="tmpl_selected_client" type="text/x-jsrender">
<table>
<table class="select_info_table">
<tr>
<td>Name:</td>
<td class="info_key"><node key="client_name"/></td>
<td><node key="client_name"/></td>
</tr>
{{if property_client_description.length > 0}}
<tr>
<td>Description:</td>
<td class="info_key">{{>property_client_description}}</td>
<td>{{>property_client_description}}</td>
</tr>
{{/if}}
<tr>
<td>Version:</td>
<td class="info_key"><a title="{{:property_client_version}}">{{*: data.property_client_version.split(" ")[0]; }}</a> on {{:property_client_platform}}</td>
<td><a title="{{>property_client_version}}">{{*: data.property_client_version.split(" ")[0]; }}</a> on {{>property_client_platform}}</td>
</tr>
<tr>
<td>Online since:</td>
<td class="info_key update_onlinetime">{{:client_onlinetime}}</td>
<td class="update_onlinetime">{{:client_onlinetime}}</td>
</tr>
<tr>
<td>Volume:</td>
<td class="info_key">{{:sound_volume}}%</td>
<td>{{:sound_volume}}%</td>
</tr>
{{if client_teaforum_id > 0}}
<tr>
<td>TeaSpeak Account:</td>
<td class="info_key"><a href="//forum.teaspeak.de/index.php?members/{{:property_client_teaforum_id}}" target="_blank">{{:property_client_teaforum_name}}</a></td>
<td><a href="//forum.teaspeak.de/index.php?members/{{:property_client_teaforum_id}}" target="_blank">{{>property_client_teaforum_name}}</a></td>
</tr>
{{/if}}
</table>
@ -362,6 +382,147 @@
<div style="margin-left: 3px">{{*: data["group_" + data.group_channel + "_name"]}}</div>
</div>
</div>
<!-- Costume tags/icons -->
<!-- Speakers/Headphones disabled -->
{{if !property_client_output_hardware}}
<div style="display: inline-flex">
<div class="icon_x32 client-hardware_output_muted" style="margin-right: 5px"></div>
<a style="align-self: center">Speakers/Headphones disabled</a>
</div>
{{/if}}
<!-- Microphone disabled -->
{{if !property_client_input_hardware}}
<div style="display: inline-flex">
<div class="icon_x32 client-hardware_input_muted" style="margin-right: 5px"></div>
<a style="align-self: center">Microphone disabled</a>
</div>
{{/if}}
<!-- Speakers/Headphones Muted -->
{{if property_client_output_muted}}
<div style="display: inline-flex">
<div class="icon_x32 client-output_muted" style="margin-right: 5px"></div>
<a style="align-self: center">Speakers/Headphones Muted</a>
</div>
{{/if}}
<!-- Microphone Muted -->
{{if property_client_input_muted}}
<div style="display: inline-flex">
<div class="icon_x32 client-input_muted" style="margin-right: 5px"></div>
<a style="align-self: center">Microphone Muted</a>
</div>
{{/if}}
</script>
<!--
let version = this.current_selected.properties.virtualserver_version;
if(version.startsWith("TeaSpeak ")) version = version.substr("TeaSpeak ".length);
this._htmlTag.append(this.createInfoTable({
"Name": this.current_selected.properties.virtualserver_name,
"Address": "unknown",
"Type": "TeaSpeak",
"Version": version + " on " + this.current_selected.properties.virtualserver_platform,
"Uptime": "<a class='uptime'>" + formatDate(this.current_selected.calculateUptime()) + "</a>",
"Current Channels": this.current_selected.properties.virtualserver_channelsonline,
"Current Clients": this.current_selected.properties.virtualserver_clientsonline,
"Current Queries": this.current_selected.properties.virtualserver_queryclientsonline
}));
-->
<script id="tmpl_selected_server" type="text/x-jsrender">
<table class="select_info_table">
<tr>
<td>Name:</td>
<td><node key="server_name"/></td>
</tr>
<tr>
<td>Address:</td>
<td>{{>server_address}}</td>
</tr>
<tr>
<td>Type:</td>
<td>TeaSpeak</td>
</tr>
<tr>
<td>Version:</td>
<td><a title="{{>property_virtualserver_version}}">{{*: data.property_virtualserver_version.split(" ")[0]; }}</a> on {{>property_virtualserver_platform}}</td>
</tr>
<tr>
<td>Uptime:</td>
<td class="update_onlinetime">{{:server_onlinetime}}</td>
</tr>
<tr>
<td>Current Channels:</td>
<td>{{:property_virtualserver_channelsonline}}</td>
</tr>
<tr>
<td>Current Clients:</td>
<td>{{:property_virtualserver_clientsonline}}</td>
</tr>
<tr>
<td>Current Queries:</td>
<td>{{:property_virtualserver_queryclientsonline}}</td>
</tr>
</table>
</script>
<script id="tmpl_selected_channel" type="text/x-jsrender">
<table class="select_info_table">
<tr>
<td>Name:</td>
<td><node key="channel_name"/></td>
</tr>
<tr>
<td>Topic:</td>
<td>{{>property_channel_topic}}</td>
</tr>
<tr>
<td>Codec:</td>
<td>{{>property_channel_codec}}</td>
</tr>
<tr>
<td>Codec Quality:</td>
<td>{{>property_channel_codec_quality}}</td>
</tr>
<tr>
<td>Type:</td>
<td>{{>channel_type}}</td>
</tr>
<tr>
<td>Current clients:</td>
<td>
{{>channel_clients}} /
{{if property_channel_maxclients == -1}}
Unlimited
{{else}}
{{>property_channel_maxclients}}
{{/if}}
</td>
</tr>
<tr>
<td>Subscription Status:</td>
<td>
{{if channel_subscribed}}
Subscribed
{{else}}
Unsubscribed
{{/if}}
</td>
</tr>
<tr>
<td>Voice Data Encryption:</td>
<td>
{{if property_channel_codec_is_unencrypted}}
Unencrypted
{{else}}
Encrypted
{{/if}}
</td>
</tr>
</table>
</script>
</body>
</html>