Reworked basic UI and added the hostbanner to the UI
parent
e3cafc5e72
commit
bbbd8f6365
|
@ -1,4 +1,8 @@
|
||||||
# Changelog:
|
# Changelog:
|
||||||
|
* **03.11.18**
|
||||||
|
- Reworked on the basic overlay sizes
|
||||||
|
- Added hostbanner to the UI
|
||||||
|
|
||||||
* **28.10.18**
|
* **28.10.18**
|
||||||
- Restructured the project
|
- Restructured the project
|
||||||
- Added a lot of helper scripts
|
- Added a lot of helper scripts
|
||||||
|
|
|
@ -26,4 +26,67 @@
|
||||||
color: green;
|
color: green;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.hostbanner {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
<div id="select_info" class="select_info" style="width: 100%; max-width: 100%">
|
||||||
|
<div class="container-banner"></div>
|
||||||
|
<div class="container-info"></div>
|
||||||
|
</div>
|
||||||
|
*/
|
||||||
|
.select_info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: stretch;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-banner {
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 2;
|
||||||
|
max-height: 25%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&:not(:disabled) {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hostbanner {
|
||||||
|
position: relative;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
img {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-select-info {
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -266,4 +266,52 @@ footer .container {
|
||||||
position: relative;
|
position: relative;
|
||||||
vertical-align: center;
|
vertical-align: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app {
|
||||||
|
.container-channel-chat {
|
||||||
|
> div {
|
||||||
|
min-height: 100px;
|
||||||
|
min-width: 100px;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
min-width: 100px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
.container-channel {
|
||||||
|
flex-grow: 60;
|
||||||
|
display: flex;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
overflow: auto;
|
||||||
|
overflow-x: visible;
|
||||||
|
|
||||||
|
|
||||||
|
background: white;
|
||||||
|
border: 2px solid lightgray;
|
||||||
|
border-right-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-chat {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
max-height: 400px;
|
||||||
|
height: 250px;
|
||||||
|
border-radius: 0 0 0 2px;
|
||||||
|
border-top-width: 0;
|
||||||
|
border-right-width: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-info {
|
||||||
|
min-width: 100px;
|
||||||
|
max-width: 40%;
|
||||||
|
width: 40%;
|
||||||
|
border-radius: 0 0 2px 0;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,6 +7,8 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#chat div {
|
#chat div {
|
||||||
|
|
|
@ -69,14 +69,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="flex-direction: row; height: 100%; width: 100%; display: flex">
|
<div style="flex-direction: row; height: 100%; width: 100%; display: flex; justify-content: stretch;">
|
||||||
<div style="width: 60%; flex-direction: column;">
|
<div class="container-channel-chat">
|
||||||
<div style="height: 60%; border-radius: 0 0 0 0; border-right-width: 0; overflow: auto; overflow-x: visible"
|
<div class="container-channel" class="main_container">
|
||||||
class="main_container">
|
|
||||||
<div class="channelTree" id="channelTree"></div>
|
<div class="channelTree" id="channelTree"></div>
|
||||||
</div> <!-- Channel tree -->
|
</div>
|
||||||
<div style="height: 40%; border-radius: 0 0 0 2px; border-top-width: 0; border-right-width: 0;"
|
<!-- Channel tree -->
|
||||||
class="main_container">
|
<div class="main_container container-chat">
|
||||||
<div id="chat">
|
<div id="chat">
|
||||||
<div class="messages">
|
<div class="messages">
|
||||||
<div class="message_box"></div>
|
<div class="message_box"></div>
|
||||||
|
@ -90,15 +89,16 @@
|
||||||
</div>
|
</div>
|
||||||
</div> <!-- Chat window -->
|
</div> <!-- Chat window -->
|
||||||
</div>
|
</div>
|
||||||
<div style="width: 40%; border-radius: 0px 0px 2px 0px;" class="main_container">
|
<div class="main_container container-info">
|
||||||
<div id="select_info" class="select_info" style="width: 100%; max-width: 100%">
|
<div id="select_info" class="select_info" style="width: 100%; max-width: 100%">
|
||||||
|
<div class="container-banner"></div>
|
||||||
|
<div class="container-select-info"></div>
|
||||||
</div>
|
</div>
|
||||||
</div> <!-- Selection info -->
|
</div> <!-- Selection info -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="contextMenu" class="context-menu"></div>
|
<div id="contextMenu" class="context-menu"></div>
|
||||||
<div style="height: 100px"></div>
|
|
||||||
</script>
|
</script>
|
||||||
<!-- Template for the connect modal -->
|
<!-- Template for the connect modal -->
|
||||||
<script class="jsrender-template" id="tmpl_connect" type="text/html">
|
<script class="jsrender-template" id="tmpl_connect" type="text/html">
|
||||||
|
@ -1320,42 +1320,84 @@
|
||||||
<node key="music_player"/>
|
<node key="music_player"/>
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
<script class="jsrender-template" id="tmpl_selected_hostbanner" type="text/html">
|
||||||
|
<div class="hostbanner">
|
||||||
|
{{if property_virtualserver_hostbanner_url}}
|
||||||
|
<a href="{{:property_virtualserver_hostbanner_url}}">
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<img src="
|
||||||
|
{{:property_virtualserver_hostbanner_gfx_url}}
|
||||||
|
{{if property_virtualserver_hostbanner_gfx_interval > 0}}
|
||||||
|
{{*
|
||||||
|
date = Math.floor(Date.now() / 1000);
|
||||||
|
if (data.property_virtualserver_hostbanner_gfx_interval <= 60)
|
||||||
|
data.property_virtualserver_hostbanner_gfx_interval = 60;
|
||||||
|
date = Math.floor(date / data.property_virtualserver_hostbanner_gfx_interval) * data.property_virtualserver_hostbanner_gfx_interval;
|
||||||
|
}}
|
||||||
|
?ts={{*:date}}
|
||||||
|
{{/if}}
|
||||||
|
"
|
||||||
|
{{if property_virtualserver_hostbanner_mode == 0}}
|
||||||
|
|
||||||
|
{{else property_virtualserver_hostbanner_mode == 1}}
|
||||||
|
style="width: 100%; height: 100%;"
|
||||||
|
{{else property_virtualserver_hostbanner_mode == 2}}
|
||||||
|
style="width: 100%; height: auto;"
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
alt="Host banner"
|
||||||
|
>
|
||||||
|
{{if property_virtualserver_hostbanner_url}}
|
||||||
|
</a>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
<script class="jsrender-template" id="tmpl_selected_server" type="text/html">
|
<script class="jsrender-template" id="tmpl_selected_server" type="text/html">
|
||||||
<div class="select_server">
|
<div class="select_server">
|
||||||
<table class="select_info_table">
|
<div class="container">
|
||||||
<tr>
|
<!--
|
||||||
<td>Name:</td>
|
virtualserver_hostbanner_url: string = "";
|
||||||
<td><node key="server_name"/></td>
|
virtualserver_hostbanner_gfx_url: string = "";
|
||||||
</tr>
|
virtualserver_hostbanner_gfx_interval: number = 0;
|
||||||
<tr>
|
virtualserver_hostbanner_mode: number = 0;
|
||||||
<td>Address:</td>
|
-->
|
||||||
<td>{{>server_address}}</td>
|
|
||||||
</tr>
|
<table class="select_info_table">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Type:</td>
|
<td>Name:</td>
|
||||||
<td>TeaSpeak</td>
|
<td><node key="server_name"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Version:</td>
|
<td>Address:</td>
|
||||||
<td><a title="{{>property_virtualserver_version}}">{{*: data.property_virtualserver_version.split(" ")[0]; }}</a> on {{>property_virtualserver_platform}}</td>
|
<td>{{>server_address}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Uptime:</td>
|
<td>Type:</td>
|
||||||
<td class="update_onlinetime">{{:server_onlinetime}}</td>
|
<td>TeaSpeak</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Current Channels:</td>
|
<td>Version:</td>
|
||||||
<td>{{:property_virtualserver_channelsonline}}</td>
|
<td><a title="{{>property_virtualserver_version}}">{{*: data.property_virtualserver_version.split(" ")[0]; }}</a> on {{>property_virtualserver_platform}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Current Clients:</td>
|
<td>Uptime:</td>
|
||||||
<td>{{:property_virtualserver_clientsonline}}</td>
|
<td class="update_onlinetime">{{:server_onlinetime}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Current Queries:</td>
|
<td>Current Channels:</td>
|
||||||
<td>{{:property_virtualserver_queryclientsonline}}</td>
|
<td>{{:property_virtualserver_channelsonline}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
<tr>
|
||||||
|
<td>Current Clients:</td>
|
||||||
|
<td>{{:property_virtualserver_clientsonline}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Current Queries:</td>
|
||||||
|
<td>{{:property_virtualserver_queryclientsonline}}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button class="button-update btn_update">Update info</button>
|
<button class="button-update btn_update">Update info</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -54,28 +54,35 @@ class InfoBar<AvailableTypes = ServerEntry | ChannelEntry | ClientEntry | undefi
|
||||||
|
|
||||||
private current_selected?: AvailableTypes;
|
private current_selected?: AvailableTypes;
|
||||||
private _htmlTag: JQuery<HTMLElement>;
|
private _htmlTag: JQuery<HTMLElement>;
|
||||||
|
private _tag_info: JQuery<HTMLElement>;
|
||||||
|
private _tag_banner: JQuery<HTMLElement>;
|
||||||
|
|
||||||
private current_manager: InfoManagerBase = undefined;
|
private current_manager: InfoManagerBase = undefined;
|
||||||
private managers: InfoManagerBase[] = [];
|
private managers: InfoManagerBase[] = [];
|
||||||
|
private banner_manager: Hostbanner;
|
||||||
|
|
||||||
constructor(client: TSClient, htmlTag: JQuery<HTMLElement>) {
|
constructor(client: TSClient, htmlTag: JQuery<HTMLElement>) {
|
||||||
this.handle = client;
|
this.handle = client;
|
||||||
this._htmlTag = htmlTag;
|
this._htmlTag = htmlTag;
|
||||||
|
this._tag_info = htmlTag.find(".container-select-info");
|
||||||
|
this._tag_banner = htmlTag.find(".container-banner");
|
||||||
|
|
||||||
this.managers.push(new MusicInfoManager());
|
this.managers.push(new MusicInfoManager());
|
||||||
this.managers.push(new ClientInfoManager());
|
this.managers.push(new ClientInfoManager());
|
||||||
this.managers.push(new ChannelInfoManager());
|
this.managers.push(new ChannelInfoManager());
|
||||||
this.managers.push(new ServerInfoManager());
|
this.managers.push(new ServerInfoManager());
|
||||||
|
|
||||||
|
this.banner_manager = new Hostbanner(client, this._tag_banner);
|
||||||
}
|
}
|
||||||
|
|
||||||
setCurrentSelected(entry: AvailableTypes) {
|
setCurrentSelected(entry: AvailableTypes) {
|
||||||
if(this.current_selected == entry) return;
|
if(this.current_selected == entry) return;
|
||||||
if(this.current_manager) {
|
if(this.current_manager) {
|
||||||
(this.current_manager as InfoManager<AvailableTypes>).finalizeFrame(this.current_selected, this._htmlTag);
|
(this.current_manager as InfoManager<AvailableTypes>).finalizeFrame(this.current_selected, this._tag_info);
|
||||||
this.current_manager = null;
|
this.current_manager = null;
|
||||||
this.current_selected = null;
|
this.current_selected = null;
|
||||||
}
|
}
|
||||||
this._htmlTag.empty();
|
this._tag_info.empty();
|
||||||
|
|
||||||
this.current_selected = entry;
|
this.current_selected = entry;
|
||||||
for(let manager of this.managers) {
|
for(let manager of this.managers) {
|
||||||
|
@ -87,7 +94,7 @@ class InfoBar<AvailableTypes = ServerEntry | ChannelEntry | ClientEntry | undefi
|
||||||
|
|
||||||
console.log("Using info manager: %o", this.current_manager);
|
console.log("Using info manager: %o", this.current_manager);
|
||||||
if(this.current_manager)
|
if(this.current_manager)
|
||||||
(this.current_manager as InfoManager<AvailableTypes>).createFrame(this, this.current_selected, this._htmlTag);
|
(this.current_manager as InfoManager<AvailableTypes>).createFrame(this, this.current_selected, this._tag_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
get currentSelected() {
|
get currentSelected() {
|
||||||
|
@ -96,7 +103,56 @@ class InfoBar<AvailableTypes = ServerEntry | ChannelEntry | ClientEntry | undefi
|
||||||
|
|
||||||
update(){
|
update(){
|
||||||
if(this.current_manager && this.current_selected)
|
if(this.current_manager && this.current_selected)
|
||||||
(this.current_manager as InfoManager<AvailableTypes>).updateFrame(this.current_selected, this._htmlTag);
|
(this.current_manager as InfoManager<AvailableTypes>).updateFrame(this.current_selected, this._tag_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
update_banner() {
|
||||||
|
this.banner_manager.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Hostbanner {
|
||||||
|
readonly html_tag: JQuery<HTMLElement>;
|
||||||
|
readonly client: TSClient;
|
||||||
|
|
||||||
|
private updater: NodeJS.Timer;
|
||||||
|
|
||||||
|
constructor(client: TSClient, htmlTag: JQuery<HTMLElement>) {
|
||||||
|
this.client = client;
|
||||||
|
this.html_tag = htmlTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
if(this.updater) {
|
||||||
|
clearTimeout(this.updater);
|
||||||
|
this.updater = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.html_tag.empty();
|
||||||
|
const tag = this.generate_tag();
|
||||||
|
|
||||||
|
if(tag) {
|
||||||
|
this.html_tag.append(tag);
|
||||||
|
this.html_tag.prop("disabled", false);
|
||||||
|
} else
|
||||||
|
this.html_tag.prop("disabled", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private generate_tag?() : JQuery<HTMLElement> {
|
||||||
|
if(!this.client.connected) return undefined;
|
||||||
|
const server = this.client.channelTree.server;
|
||||||
|
if(!server) return undefined;
|
||||||
|
if(!server.properties.virtualserver_hostbanner_gfx_url) return undefined;
|
||||||
|
|
||||||
|
let properties: any = {};
|
||||||
|
for(let key in server.properties)
|
||||||
|
properties["property_" + key] = server.properties[key];
|
||||||
|
|
||||||
|
const rendered = $("#tmpl_selected_hostbanner").renderTag(properties);
|
||||||
|
|
||||||
|
if(server.properties.virtualserver_hostbanner_gfx_interval > 0)
|
||||||
|
this.updater = setTimeout(() => this.update(), Math.min(server.properties.virtualserver_hostbanner_gfx_interval, 60) * 1000);
|
||||||
|
return rendered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,7 @@ class ServerEntry {
|
||||||
updateVariables(is_self_notify: boolean, ...variables: {key: string, value: string}[]) {
|
updateVariables(is_self_notify: boolean, ...variables: {key: string, value: string}[]) {
|
||||||
let group = log.group(log.LogType.DEBUG, LogCategory.SERVER, "Update properties (%i)", variables.length);
|
let group = log.group(log.LogType.DEBUG, LogCategory.SERVER, "Update properties (%i)", variables.length);
|
||||||
|
|
||||||
|
let update_bannner = false;
|
||||||
for(let variable of variables) {
|
for(let variable of variables) {
|
||||||
JSON.map_field_to(this.properties, variable.value, variable.key);
|
JSON.map_field_to(this.properties, variable.value, variable.key);
|
||||||
|
|
||||||
|
@ -150,8 +151,12 @@ class ServerEntry {
|
||||||
} else if(variable.key == "virtualserver_icon_id") {
|
} else if(variable.key == "virtualserver_icon_id") {
|
||||||
if(this.channelTree.client.fileManager && this.channelTree.client.fileManager.icons)
|
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"));
|
this.htmlTag.find(".icon_property").replaceWith(this.channelTree.client.fileManager.icons.generateTag(this.properties.virtualserver_icon_id).addClass("icon_property"));
|
||||||
|
} else if(variable.key.indexOf('hostbanner') != -1) {
|
||||||
|
update_bannner = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(update_bannner)
|
||||||
|
this.channelTree.client.selectInfo.update_banner();
|
||||||
|
|
||||||
group.end();
|
group.end();
|
||||||
if(is_self_notify && this.info_request_promise_resolve) {
|
if(is_self_notify && this.info_request_promise_resolve) {
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
html, body {
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-container {
|
.app-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
.app {
|
.app {
|
||||||
width: 1200px;
|
width: 100%;
|
||||||
height: 900px;
|
height: calc(100% - 50px);
|
||||||
display: flex;
|
margin: 0;
|
||||||
flex-direction: column;
|
|
||||||
resize: both;
|
display: flex; flex-direction: column; resize: both;
|
||||||
margin: 20px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue