TeaWeb/shared/js/ui/modal/ModalMusicManage.ts

1905 lines
73 KiB
TypeScript
Raw Normal View History

2020-03-30 13:44:18 +02:00
import {createErrorModal, createModal} from "tc-shared/ui/elements/Modal";
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
import {MusicClientEntry} from "tc-shared/ui/client";
import {Registry} from "tc-shared/events";
import {CommandResult, ErrorID} from "tc-shared/connection/ServerConnectionDeclaration";
import {LogCategory} from "tc-shared/log";
import * as log from "tc-shared/log";
import {tra} from "tc-shared/i18n/localize";
import * as tooltip from "tc-shared/ui/elements/Tooltip";
import { modal } from "tc-shared/events";
import * as i18nc from "tc-shared/i18n/country";
import {find} from "tc-shared/permission/PermissionManager";
import ServerGroup = find.ServerGroup;
import * as htmltags from "tc-shared/ui/htmltags";
export function openMusicManage(client: ConnectionHandler, bot: MusicClientEntry) {
const ev_registry = new Registry<modal.music_manage>();
ev_registry.enable_debug("music-manage");
//dummy_controller(ev_registry);
permission_controller(ev_registry, bot, client);
let modal = createModal({
header: tr(tr("Playlist Manage")),
body: () => build_modal(ev_registry),
footer: null,
min_width: "35em",
closeable: true
});
modal.htmlTag.find(".modal-body").addClass("modal-music-manage");
/* "controller" */
{
2020-02-22 14:30:17 +01:00
}
2020-03-30 13:44:18 +02:00
modal.open();
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
function permission_controller(event_registry: Registry<modal.music_manage>, bot: MusicClientEntry, client: ConnectionHandler) {
const error_msg = error => {
if(error instanceof CommandResult) {
if(error.id === ErrorID.PERMISSION_ERROR) {
const permission = client.permissions.resolveInfo(error.json["failed_permid"]);
return tr("failed on permission ") + (permission ? permission.name : tr("unknown"));
}
return error.extra_message || error.message;
} else if(typeof error === "string")
return error;
else
return tr("command error");
};
{
event_registry.on("query_playlist_status", event => {
const playlist_id = bot.properties.client_playlist_id;
client.serverConnection.command_helper.request_playlist_info(playlist_id).then(result => {
event_registry.fire("playlist_status", {
status: "success",
data: {
replay_mode: result.playlist_replay_mode,
finished: result.playlist_flag_finished,
delete_played: result.playlist_flag_delete_played,
notify_song_change: bot.properties.client_flag_notify_song_change,
max_size: result.playlist_max_songs
2020-02-22 14:30:17 +01:00
}
});
2020-03-30 13:44:18 +02:00
}).catch(error => {
event_registry.fire("playlist_status", {
status: "error",
error_msg: error_msg(error)
});
log.error(LogCategory.CLIENT, tr("Failed to query playlist info for playlist %d: %o"), playlist_id, error);
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_playlist_status", event => {
const playlist_id = bot.properties.client_playlist_id;
const property_map = {
"replay_mode": "playlist_replay_mode",
"finished": "playlist_flag_finished",
"delete_played": "playlist_flag_delete_played",
"max_size": "playlist_max_songs"
};
Promise.resolve().then(() => {
if(event.key === "notify_song_change") {
return client.serverConnection.send_command("clientedit", {
clid: bot.clientId(),
client_flag_notify_song_change: event.value
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
} else {
2020-02-22 14:30:17 +01:00
const property = property_map[event.key];
if(!property) return Promise.reject(tr("unknown property"));
const data = {
2020-03-30 13:44:18 +02:00
playlist_id: playlist_id
2020-02-22 14:30:17 +01:00
};
data[property] = event.value;
2020-03-30 13:44:18 +02:00
return client.serverConnection.send_command("playlistedit", data);
}
}).then(() => {
event_registry.fire("set_playlist_status_result", {
status: "success",
key: event.key,
value: event.value
});
}).catch(error => {
event_registry.fire("set_playlist_status_result", {
status: "error",
key: event.key,
error_msg: error_msg(error)
});
log.error(LogCategory.CLIENT, tr("Failed to change playlist status %s for playlist %d: %o"), event.key, playlist_id, error);
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_bot_status", event => {
setTimeout(() => {
event_registry.fire("bot_status", {
status: "success",
data: {
channel_commander: bot.properties.client_is_channel_commander,
volume: bot.properties.player_volume,
description: bot.properties.client_description,
default_country_code: (
!bot.channelTree ? undefined :
!bot.channelTree.server ? undefined : bot.channelTree.server.properties.virtualserver_country_code) || "DE",
country_code: bot.properties.client_country,
name: bot.properties.client_nickname,
priority_speaker: bot.properties.client_is_priority_speaker,
bot_type: bot.properties.client_bot_type,
client_platform: bot.properties.client_platform,
client_version: bot.properties.client_version,
uptime_mode: bot.properties.client_uptime_mode
}
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
}, 0);
});
event_registry.on("set_bot_status", event => {
const property_map = {
"channel_commander": "client_is_channel_commander",
"volume": "player_volume",
"description": "client_description",
"country_code": "client_country",
"name": "client_nickname",
"priority_speaker": "client_is_priority_speaker",
"bot_type": "client_bot_type",
"client_platform": "client_platform",
"client_version": "client_version",
"uptime_mode": "client_uptime_mode"
};
Promise.resolve().then(() => {
const property = property_map[event.key];
if(!property) return Promise.reject(tr("unknown property"));
const data = {
clid: bot.clientId()
};
data[property] = event.value;
return client.serverConnection.send_command("clientedit", data);
}).then(() => {
event_registry.fire("set_bot_status_result", {
status: "success",
key: event.key,
value: event.value
});
}).catch(error => {
event_registry.fire("set_bot_status_result", {
status: "error",
key: event.key,
error_msg: error_msg(error)
});
log.error(LogCategory.CLIENT, tr("Failed to change bot setting %s: %o"), event.key, error);
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* permissions */
{
event_registry.on("query_general_permissions", event => {
const playlist_id = bot.properties.client_playlist_id;
client.permissions.requestPlaylistPermissions(playlist_id).then(result => {
const permissions = {};
for(const permission of result)
if(permission.hasValue())
permissions[permission.type.name] = permission.value;
event_registry.fire("general_permissions", {
status: "success",
permissions: permissions
});
}).catch(error => {
event_registry.fire("general_permissions", {
status: "error",
error_msg: error_msg(error)
});
log.error(LogCategory.CLIENT, tr("Failed to query playlist general permissions for playlist %d: %o"), playlist_id, error);
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_general_permission", event => {
const playlist_id = bot.properties.client_playlist_id;
client.serverConnection.send_command("playlistaddperm", {
playlist_id: playlist_id,
permsid: event.key,
permvalue: event.value,
permskip: false,
permnegated: false
}).then(() => {
event_registry.fire("set_general_permission_result", {
key: event.key,
status: "success",
value: event.value
});
}).catch(error => {
event_registry.fire("set_general_permission_result", {
status: "error",
key: event.key,
error_msg: error_msg(error)
});
log.error(LogCategory.CLIENT, tr("Failed to set playlist general permissions for playlist %d and permission %d: %o"), playlist_id, event.key, error);
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_client_permissions", event => {
const playlist_id = bot.properties.client_playlist_id;
const client_id = event.client_database_id;
client.permissions.requestPlaylistClientPermissions(playlist_id, client_id).then(result => {
const permissions = {};
for(const permission of result)
if(permission.hasValue())
permissions[permission.type.name] = permission.value;
event_registry.fire("client_permissions", {
status: "success",
client_database_id: event.client_database_id,
permissions: permissions
});
}).catch(error => {
event_registry.fire("client_permissions", {
status: "error",
client_database_id: event.client_database_id,
error_msg: error_msg(error)
});
log.error(LogCategory.CLIENT, tr("Failed to query playlist client permissions for playlist %d and client %d: %o"), playlist_id, client_id, error);
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_client_permission", event => {
const playlist_id = bot.properties.client_playlist_id;
const client_id = event.client_database_id;
client.serverConnection.send_command("playlistclientaddperm", {
playlist_id: playlist_id,
cldbid: client_id,
permsid: event.key,
permvalue: event.value,
permskip: false,
permnegated: false
}).then(() => {
event_registry.fire("set_client_permission_result", {
key: event.key,
status: "success",
client_database_id: client_id,
value: event.value
});
}).catch(error => {
event_registry.fire("set_client_permission_result", {
status: "error",
key: event.key,
client_database_id: client_id,
error_msg: error_msg(error)
});
log.error(LogCategory.CLIENT, tr("Failed to set playlist client permissions for playlist %d, permission %d and client id %d: %o"), playlist_id, event.key, client_id, error);
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_special_clients", event => {
const playlist_id = bot.properties.client_playlist_id;
client.serverConnection.command_helper.request_playlist_client_list(playlist_id).then(clients => {
return client.serverConnection.command_helper.info_from_cldbid(...clients);
}).then(clients => {
event_registry.fire("special_client_list", {
status: "success",
clients: clients.map(e => {
return {
name: e.client_nickname,
unique_id: e.client_unique_id,
database_id: e.client_database_id
}
})
});
}).catch(error => {
event_registry.fire("special_client_list", {
status: "error",
error_msg: error_msg(error)
});
log.error(LogCategory.CLIENT, tr("Failed to query special client list for playlist %d: %o"), playlist_id, error);
})
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("search_client", event => {
if(!event.text) return;
const text = event.text;
Promise.resolve().then(() => {
let is_uuid = false;
try {
is_uuid = atob(text).length === 32;
} catch(e) {}
if(is_uuid) {
return client.serverConnection.command_helper.info_from_uid(text);
} else if(text.match(/^[0-9]{1,7}$/) && !isNaN(parseInt(text))) {
return client.serverConnection.command_helper.info_from_cldbid(parseInt(text));
} else {
//TODO: Database name lookup?
return Promise.reject("no results");
}
}).then(result => {
if(result.length) {
const client = result[0];
2020-02-22 14:30:17 +01:00
event_registry.fire("search_client_result", {
2020-03-30 13:44:18 +02:00
status: "success",
client: {
name: client.client_nickname,
unique_id: client.client_unique_id,
database_id: client.client_database_id
}
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
} else {
event_registry.fire("search_client_result", {
status: "empty"
});
}
}).catch(error => {
event_registry.fire("search_client_result", {
status: "error",
error_msg: error_msg(error)
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
log.error(LogCategory.CLIENT, tr("Failed to lookup search text \"%s\": %o"), text, error);
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_group_permissions", event => {
client.permissions.find_permission(event.permission_name).then(result => {
let groups = [];
for(const e of result) {
if(e.type !== "server_group") continue;
2020-02-22 14:30:17 +01:00
2020-06-13 18:47:05 +02:00
const group = client.groups.findServerGroup((e as ServerGroup).group_id);
2020-03-30 13:44:18 +02:00
if(!group) continue;
groups.push({
name: group.name,
value: e.value,
id: group.id
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
}
event_registry.fire("group_permissions", {
status: "success",
groups: groups,
permission_name: event.permission_name
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
}).catch(error => {
event_registry.fire("group_permissions", {
status: "error",
error_msg: error_msg(error),
permission_name: event.permission_name
});
log.error(LogCategory.CLIENT, tr("Failed to execute permfind for permission %s: %o"), event.permission_name, error);
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
2020-02-22 14:30:17 +01:00
}
2020-03-30 13:44:18 +02:00
}
function dummy_controller(event_registry: Registry<modal.music_manage>) {
/* settings */
{
event_registry.on("query_bot_status", event => {
setTimeout(() => {
event_registry.fire("bot_status", {
status: "success",
data: {
name: "Another TeaSpeak bot",
country_code: "DE",
default_country_code: "GB",
channel_commander: false,
description: "Hello World",
priority_speaker: true,
volume: 66,
uptime_mode: 0,
client_version: "Version",
client_platform: "Platform",
bot_type: 0
}
})
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_playlist_status", event => {
setTimeout(() => {
event_registry.fire("playlist_status", {
status: "success",
data: {
max_size: 55,
notify_song_change: true,
delete_played: false,
finished: false,
replay_mode: 2
}
})
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* permissions */
{
event_registry.on("query_special_clients", event => {
setTimeout(() => {
event_registry.fire("special_client_list", {
status: "success",
clients: [{
name: "WolverinDEV",
database_id: 1,
unique_id: "abd"
}, {
name: "WolverinDEV 2",
database_id: 2,
unique_id: "abd1"
}, {
name: "WolverinDEV 3",
database_id: 3,
unique_id: "abd1"
}]
});
}, 0);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_group_permissions", event => {
setTimeout(() => {
event_registry.fire("group_permissions", {
status: "success",
groups: [{
value: 20,
name: "Server Admin p:20",
id: 0
}, {
value: 10,
name: "Server Mod p:10",
id: 0
}],
permission_name: event.permission_name
});
}, 0);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_general_permissions", event => {
setTimeout(() => {
event_registry.fire("general_permissions", {
status: "success",
permissions: {
i_playlist_song_needed_add_power: 77
}
})
}, 0);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_general_permission", event => {
setTimeout(() => {
event_registry.fire("set_general_permission_result", {
key: event.key,
value: event.value,
status: "success"
2020-02-22 14:30:17 +01:00
});
});
2020-03-30 13:44:18 +02:00
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_client_permissions", event => {
setTimeout(() => {
event_registry.fire("client_permissions", {
client_database_id: event.client_database_id,
status: "success",
permissions: {
i_playlist_song_needed_add_power: 77
}
})
}, 500);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_client_permission", event => {
setTimeout(() => {
event_registry.fire("set_client_permission_result", {
key: event.key,
client_database_id: event.client_database_id,
status: "success",
value: event.value
})
}, 500);
});
2020-02-22 14:30:17 +01:00
}
2020-03-30 13:44:18 +02:00
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
function build_modal(event_registry: Registry<modal.music_manage>) : JQuery<HTMLElement> {
const tag = $("#tmpl_music_manage").renderTag();
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const container_settings = tag.find(".body > .category-settings");
build_settings_container(event_registry, container_settings);
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const container_permissions = tag.find(".body > .category-permissions");
build_permission_container(event_registry, container_permissions);
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* general switch */
{
let shown_container: "settings" | "permissions";
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const header = tag.find(".header");
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const category_permissions = header.find(".category-permissions");
event_registry.on("show_container", data => {
category_permissions.toggleClass("selected", data.container === "permissions");
container_permissions.toggleClass("hidden", data.container !== "permissions");
});
category_permissions.on('click', event => {
if(shown_container === "permissions") return;
event_registry.fire("show_container", { container: "permissions" });
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const category_settings = header.find(".category-settings");
event_registry.on("show_container", data => {
category_settings.toggleClass("selected", data.container === "settings");
container_settings.toggleClass("hidden", data.container !== "settings");
});
category_settings.on('click', event => {
if(shown_container === "settings") return;
event_registry.fire("show_container", { container: "settings" });
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
event_registry.on("show_container", data => shown_container = data.container);
2020-02-22 14:30:17 +01:00
}
2020-03-30 13:44:18 +02:00
/* input length fix */
tag.find("input[maxlength]").on("input", event => {
const input = event.target as HTMLInputElement;
const max = parseInt(input.getAttribute("maxlength"));
const text = input.value;
if(!isNaN(max) && text && text.length > max)
//input.value = text.substr(text.length - max);
input.value = text.substr(0, max);
});
/* initialize */
event_registry.fire("show_container", { container: "settings" });
return tag.children();
}
function build_settings_container(event_registry: Registry<modal.music_manage>, tag: JQuery<HTMLElement>) {
const show_change_error = (header, message) => {
createErrorModal(tr("Failed to change value"), header + "<br>" + message).open();
};
/* music bot settings */
{
const container = tag.find(".settings-bot");
/* bot name */
2020-02-22 14:30:17 +01:00
{
2020-03-30 13:44:18 +02:00
const input = container.find(".option-bot-name");
let last_value = undefined;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_bot_status", event => {
last_value = undefined;
input
.prop("disabled", true)
.val(null)
.attr("placeholder", tr("loading..."));
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("bot_status", event => {
if(event.status === "error")
2020-02-22 14:30:17 +01:00
input
.prop("disabled", true)
.val(null)
2020-03-30 13:44:18 +02:00
.attr("placeholder", event.error_msg || tr("error while loading"));
else
2020-02-22 14:30:17 +01:00
input
.prop("disabled", false)
.attr("placeholder", null)
2020-03-30 13:44:18 +02:00
.val(last_value = event.data.name);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_bot_status_result", event => {
if(event.key !== "name") return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
if(event.status !== "success")
show_change_error(tr("Failed to set bot name"), event.error_msg || tr("timeout"));
else
last_value = event.value;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input
.prop("disabled", false)
.attr("placeholder", null)
.val(last_value);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input.on("keyup", event => event.key === "Enter" && input.trigger("focusout"));
input.on("focusout", event => {
const value = input.val() as string;
if(value === last_value) return;
if(!value) {
input.val(last_value);
return;
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input
.prop("disabled", true)
.val(null)
.attr("placeholder", tr("applying..."));
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.fire("set_bot_status", {
key: "name",
value: value
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
}
/* country flag */
{
const input = container.find(".option-bot-country");
const flag = container.find(".container-country .country");
let last_value = undefined, fallback_country = undefined;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const update_country_code = input => {
input = input || fallback_country || "ts";
flag.each((_, e) => {
for(const [index, klass] of e.classList.entries())
if(klass.startsWith("flag-"))
e.classList.remove(klass);
});
flag.addClass("flag-" + input.toLowerCase());
flag.attr("title", i18nc.country_name(input, tr("Unknown country")));
};
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_bot_status", event => {
last_value = undefined;
input
.prop("disabled", true)
.val(null)
.attr("placeholder", "...");
update_country_code("ts");
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("bot_status", event => {
if(event.status === "error")
input
.prop("disabled", true)
.val(null)
.attr("placeholder", "err");
else {
2020-02-22 14:30:17 +01:00
input
.prop("disabled", false)
.attr("placeholder", null)
2020-03-30 13:44:18 +02:00
.val(last_value = event.data.country_code);
fallback_country = event.data.default_country_code;
}
update_country_code(last_value);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_bot_status_result", event => {
if(event.key !== "country_code") return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
if(event.status !== "success")
show_change_error(tr("Failed to set bots country"), event.error_msg || tr("timeout"));
else
last_value = event.value;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input
.prop("disabled", false)
.attr("placeholder", null)
.val(last_value);
update_country_code(last_value);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input.on("input", () => {
update_country_code(input.val());
input.firstParent(".input-boxed").removeClass("is-invalid");
});
input.on("keyup", event => event.key === "Enter" && input.trigger("focusout"));
input.on("focusout", event => {
const value = input.val() as string;
if(value === last_value) return;
if(value && value.length != 2) {
input.firstParent(".input-boxed").addClass("is-invalid");
return;
}
input
.prop("disabled", true)
.val(null)
.attr("placeholder", "...");
event_registry.fire("set_bot_status", {
key: "country_code",
value: value
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* flag channel commander */
{
const input = container.find(".option-channel-commander") as JQuery<HTMLInputElement>;
const label = input.parents("label");
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
let last_value = undefined;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_bot_status", event => {
last_value = undefined;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
label.addClass("disabled");
input
.prop("checked", false)
.prop("disabled", true);
});
event_registry.on("bot_status", event => {
if(event.status === "error") {
2020-02-22 14:30:17 +01:00
label.addClass("disabled");
input
.prop("checked", false)
.prop("disabled", true);
2020-03-30 13:44:18 +02:00
} else {
label.removeClass("disabled");
input
.prop("checked", last_value = event.data.channel_commander)
.prop("disabled", false);
}
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_bot_status_result", event => {
if(event.key !== "channel_commander") return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
if(event.status !== "success")
show_change_error(tr("Failed to change channel commander state"), event.error_msg || tr("timeout"));
else
last_value = event.value;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
label.removeClass("disabled");
input
.prop("checked", last_value)
.prop("disabled", false);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input.on("change", event => {
label.addClass("disabled");
input.prop("disabled", true);
event_registry.fire("set_bot_status", {
key: "channel_commander",
value: input.prop("checked")
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* flag priority speaker */
{
const input = container.find(".option-priority-speaker") as JQuery<HTMLInputElement>;
const label = input.parents("label");
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
let last_value = undefined;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_bot_status", event => {
last_value = undefined;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
label.addClass("disabled");
input
.prop("checked", false)
.prop("disabled", true);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("bot_status", event => {
if(event.status === "error") {
2020-02-22 14:30:17 +01:00
label.addClass("disabled");
input
.prop("checked", false)
.prop("disabled", true);
2020-03-30 13:44:18 +02:00
} else {
2020-02-22 14:30:17 +01:00
label.removeClass("disabled");
input
2020-03-30 13:44:18 +02:00
.prop("checked", last_value = event.data.priority_speaker)
2020-02-22 14:30:17 +01:00
.prop("disabled", false);
2020-03-30 13:44:18 +02:00
}
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_bot_status_result", event => {
if(event.key !== "priority_speaker") return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
if(event.status !== "success")
show_change_error(tr("Failed to change priority speaker state"), event.error_msg || tr("timeout"));
else
last_value = event.value;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
label.removeClass("disabled");
input
.prop("checked", last_value)
.prop("disabled", false);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input.on("change", event => {
label.addClass("disabled");
input.prop("disabled", true);
event_registry.fire("set_bot_status", {
key: "priority_speaker",
value: input.prop("checked")
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* status load timeout */
{
let timeout;
event_registry.on("query_bot_status", event => {
timeout = setTimeout(() => {
event_registry.fire("bot_status", {
status: "error",
error_msg: tr("load timeout")
});
}, 5000);
});
event_registry.on("bot_status", event => clearTimeout(timeout));
2020-02-22 14:30:17 +01:00
}
2020-03-30 13:44:18 +02:00
/* set status timeout */
2020-02-22 14:30:17 +01:00
{
2020-03-30 13:44:18 +02:00
let timeouts: {[key: string]:any} = {};
event_registry.on("set_bot_status", event => {
clearTimeout(timeouts[event.key]);
timeouts[event.key] = setTimeout(() => {
event_registry.fire("set_bot_status_result", {
status: "timeout",
key: event.key,
});
}, 5000);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_bot_status_result", event => {
clearTimeout(timeouts[event.key]);
delete timeouts[event.key];
});
}
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* music bot settings */
{
const container = tag.find(".settings-playlist");
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* playlist replay mode */
{
const input = container.find(".option-replay-mode") as JQuery<HTMLSelectElement>;
let last_value = undefined;
const update_value = text => {
if(text) {
input.prop("disabled", true).addClass("disabled");
input.val("-1");
input.find("option[value=-1]").text(text);
} else if(last_value >= 0 && last_value <= 3) {
input
.prop("disabled", false)
.removeClass("disabled");
input.val(last_value);
} else {
update_value(tr("invalid value"));
}
};
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_playlist_status", event => {
last_value = undefined;
update_value(tr("loading..."));
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("playlist_status", event => {
if(event.status === "error") {
update_value(event.error_msg || tr("error while loading"));
} else {
last_value = event.data.replay_mode;
2020-02-22 14:30:17 +01:00
update_value(undefined);
2020-03-30 13:44:18 +02:00
}
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_playlist_status_result", event => {
if(event.key !== "replay_mode") return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
if(event.status !== "success")
show_change_error(tr("Failed to change replay mode"), event.error_msg || tr("timeout"));
else
last_value = event.value;
update_value(undefined);
});
input.on("keyup", event => event.key === "Enter" && input.trigger("focusout"));
input.on("change", event => {
const value = parseInt(input.val() as string);
console.log(value);
if(isNaN(value)) return;
update_value(tr("applying..."));
event_registry.fire("set_playlist_status", {
key: "replay_mode",
value: value
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* playlist max size */
{
const input = container.find(".container-max-playlist-size input");
let last_value = undefined;
event_registry.on("query_playlist_status", event => {
last_value = undefined;
input
.prop("disabled", true)
.val(null)
.attr("placeholder", tr("loading..."))
.firstParent(".input-boxed").addClass("disabled");
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("playlist_status", event => {
if(event.status === "error")
2020-02-22 14:30:17 +01:00
input
.prop("disabled", true)
.val(null)
2020-03-30 13:44:18 +02:00
.attr("placeholder", event.error_msg || tr("error while loading"))
2020-02-22 14:30:17 +01:00
.firstParent(".input-boxed").addClass("disabled");
2020-03-30 13:44:18 +02:00
else
2020-02-22 14:30:17 +01:00
input
.prop("disabled", false)
.attr("placeholder", null)
2020-03-30 13:44:18 +02:00
.val((last_value = event.data.max_size).toString())
2020-02-22 14:30:17 +01:00
.firstParent(".input-boxed").removeClass("disabled");
2020-03-30 13:44:18 +02:00
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_playlist_status_result", event => {
if(event.key !== "max_size") return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
if(event.status !== "success")
show_change_error(tr("Failed to change max playlist size"), event.error_msg || tr("timeout"));
else
last_value = event.value;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input
.prop("disabled", false)
.attr("placeholder", null)
.val(last_value)
.firstParent(".input-boxed").removeClass("disabled");
});
input.on("input", event => input.parentsUntil(".input-boxed").removeClass("is-invalid"));
input.on("keyup", event => event.key === "Enter" && input.trigger("focusout"));
input.on("focusout", event => {
const value = input.val() as string;
if(value === last_value) return;
if(value === "") {
input.val(last_value);
return;
}
if(isNaN(parseInt(value))) {
input.parentsUntil(".input-boxed").addClass("is-invalid");
return;
}
input
.prop("disabled", true)
.val(null)
.attr("placeholder", tr("applying..."))
.firstParent(".input-boxed").addClass("disabled");
event_registry.fire("set_playlist_status", {
key: "max_size",
value: parseInt(value)
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* flag delete played */
{
const input = container.find(".option-delete-played-songs") as JQuery<HTMLInputElement>;
const label = input.parents("label");
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
let last_value = undefined;
event_registry.on("query_playlist_status", event => {
last_value = undefined;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
label.addClass("disabled");
input
.prop("checked", false)
.prop("disabled", true);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("playlist_status", event => {
if(event.status === "error") {
2020-02-22 14:30:17 +01:00
label.addClass("disabled");
input
.prop("checked", false)
.prop("disabled", true);
2020-03-30 13:44:18 +02:00
} else {
label.removeClass("disabled");
input
.prop("checked", last_value = event.data.delete_played)
.prop("disabled", false);
}
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_playlist_status_result", event => {
if(event.key !== "delete_played") return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
if(event.status !== "success")
show_change_error(tr("Failed to change delete state"), event.error_msg || tr("timeout"));
else
last_value = event.value;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
label.removeClass("disabled");
input
.prop("checked", last_value)
.prop("disabled", false);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input.on("change", event => {
label.addClass("disabled");
input.prop("disabled", true);
event_registry.fire("set_playlist_status", {
key: "delete_played",
value: input.prop("checked")
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* flag notify song change */
{
const input = container.find(".option-notify-songs-change") as JQuery<HTMLInputElement>;
const label = input.parents("label");
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
let last_value = undefined;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_playlist_status", event => {
last_value = undefined;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
label.addClass("disabled");
input
.prop("checked", false)
.prop("disabled", true);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("playlist_status", event => {
if(event.status === "error") {
2020-02-22 14:30:17 +01:00
label.addClass("disabled");
input
.prop("checked", false)
.prop("disabled", true);
2020-03-30 13:44:18 +02:00
} else {
2020-02-22 14:30:17 +01:00
label.removeClass("disabled");
input
2020-03-30 13:44:18 +02:00
.prop("checked", last_value = event.data.notify_song_change)
2020-02-22 14:30:17 +01:00
.prop("disabled", false);
2020-03-30 13:44:18 +02:00
}
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_playlist_status_result", event => {
if(event.key !== "notify_song_change") return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
if(event.status !== "success")
show_change_error(tr("Failed to change notify state"), event.error_msg || tr("timeout"));
else
last_value = event.value;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
label.removeClass("disabled");
input
.prop("checked", last_value)
.prop("disabled", false);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input.on("change", event => {
label.addClass("disabled");
input.prop("disabled", true);
event_registry.fire("set_playlist_status", {
key: "notify_song_change",
value: input.prop("checked")
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
2020-02-22 14:30:17 +01:00
}
2020-03-30 13:44:18 +02:00
/* status load timeout */
2020-02-22 14:30:17 +01:00
{
let timeout;
2020-03-30 13:44:18 +02:00
event_registry.on("query_playlist_status", event => {
timeout = setTimeout(() => {
event_registry.fire("playlist_status", {
status: "error",
error_msg: tr("load timeout")
});
}, 5000);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("playlist_status", event => clearTimeout(timeout));
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* set status timeout */
{
let timeouts: {[key: string]:any} = {};
event_registry.on("set_playlist_status", event => {
clearTimeout(timeouts[event.key]);
timeouts[event.key] = setTimeout(() => {
event_registry.fire("set_playlist_status_result", {
status: "timeout",
key: event.key,
});
}, 5000);
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
event_registry.on("set_playlist_status_result", event => {
clearTimeout(timeouts[event.key]);
delete timeouts[event.key];
2020-02-22 14:30:17 +01:00
});
}
2020-03-30 13:44:18 +02:00
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* reload button */
{
const button = tag.find(".button-reload");
let timeout;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on(["query_bot_status", "query_playlist_status"], event => {
button.prop("disabled", true);
clearTimeout(timeout);
timeout = setTimeout(() => {
button.prop("disabled", false);
}, 1000);
});
button.on("click", event => {
event_registry.fire("query_bot_status");
event_registry.fire("query_playlist_status");
});
}
tooltip.initialize(tag);
/* initialize on show */
{
let initialized = false;
event_registry.on("show_container", event => {
if(event.container !== "settings" || initialized) return;
initialized = true;
event_registry.fire("query_bot_status");
event_registry.fire("query_playlist_status");
});
}
}
function build_permission_container(event_registry: Registry<modal.music_manage>, tag: JQuery<HTMLElement>) {
/* client search mechanism */
{
const container = tag.find(".table-head .column-client-specific .client-select");
let list_shown = false;
/* search list show/hide */
2020-02-22 14:30:17 +01:00
{
2020-03-30 13:44:18 +02:00
const button_list_clients = container.find(".button-list-clients");
button_list_clients.on('click', event =>
event_registry.fire(list_shown ? "hide_client_list" : "show_client_list"));
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("show_client_list", () => {
list_shown = true;
button_list_clients.text(tr("Hide clients"));
});
event_registry.on("hide_client_list", () => {
list_shown = false;
button_list_clients.text(tr("List clients"));
2020-02-22 14:30:17 +01:00
});
}
2020-03-30 13:44:18 +02:00
/* the search box */
2020-02-22 14:30:17 +01:00
{
2020-03-30 13:44:18 +02:00
const input_search = container.find(".input-search");
const button_search = container.find(".button-search");
let search_timeout;
let last_query;
input_search.on('keyup', event => {
const text = input_search.val() as string;
if(text === last_query) return;
if(text)
event_registry.fire("filter_client_list", { filter: text });
else
event_registry.fire("filter_client_list", { filter: undefined });
input_search.toggleClass("is-invalid", !list_shown && text === last_query);
if(!list_shown) {
button_search.prop("disabled", !text || !!search_timeout);
} else {
last_query = text;
}
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input_search.on('keydown', event => {
if(event.key === "Enter" && !list_shown && !button_search.prop("disabled"))
button_search.trigger("click");
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("show_client_list", () => {
button_search.prop("disabled", true);
input_search.attr("placeholder", tr("Search client list"));
});
event_registry.on("hide_client_list", () => {
button_search.prop("disabled", !input_search.val() || !!search_timeout);
input_search.attr("placeholder", tr("Client uid or database id"));
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
button_search.on("click", event => {
button_search.prop("disabled", true);
input_search.blur();
const text = input_search.val() as string;
last_query = text;
event_registry.fire("search_client", {
text: text
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
search_timeout = setTimeout(() => event_registry.fire("search_client_result", {
status: "timeout"
}), 5000);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("search_client_result", event => {
clearTimeout(search_timeout);
search_timeout = 0;
button_search.prop("disabled", !input_search.val());
if(event.status === "timeout") {
createErrorModal(tr("Client search failed"), tr("Failed to perform client search.<br>Search resulted in a timeout.")).open();
return;
} else if(event.status === "error" || event.status === "empty") {
//TODO: Display the error somehow?
input_search.addClass("is-invalid");
return;
} else {
event_registry.fire("special_client_set", {
client: event.client
});
}
});
}
/* the client list */
{
const container = tag.find(".overlay-client-list");
event_registry.on("show_client_list", () => container.removeClass("hidden"));
event_registry.on("hide_client_list", () => container.addClass("hidden"));
const button_refresh = container.find(".button-clientlist-refresh");
const container_entries = container.find(".container-client-list");
event_registry.on("special_client_list", data => {
button_refresh.prop("disabled", false);
container.find(".overlay").addClass("hidden");
if(data.status === "error-permission") {
const overlay = container.find(".overlay-query-error-permissions");
overlay.find("a").text(tr("Insufficient permissions"));
overlay.removeClass("hidden");
} else if(data.status === "success") {
container_entries.find(".client").remove(); /* clear */
if(!data.clients.length) {
const overlay = container.find(".overlay-empty-list");
overlay.removeClass("hidden");
2020-02-22 14:30:17 +01:00
} else {
2020-03-30 13:44:18 +02:00
for(const client of data.clients) {
const tag = $.spawn("div").addClass("client").append(
htmltags.generate_client_object({
add_braces: false,
client_id: 0,
client_database_id: client.database_id,
client_name: client.name,
client_unique_id: client.unique_id
})
);
tag.on('dblclick', event => event_registry.fire("special_client_set", { client: client }));
tag.attr("x-filter", client.database_id + "_" + client.name + "_" + client.unique_id);
container_entries.append(tag);
}
2020-02-22 14:30:17 +01:00
}
2020-03-30 13:44:18 +02:00
} else {
const overlay = container.find(".overlay-query-error");
overlay.find("a").text(data.error_msg ? data.error_msg : tr("query failed"));
overlay.removeClass("hidden");
}
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* refresh button */
button_refresh.on('click', event => {
button_refresh.prop("disabled", true);
event_registry.fire("query_special_clients");
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* special client list query timeout handler */
{
let query_timeout;
event_registry.on("query_special_clients", event => {
query_timeout = setTimeout(() => {
event_registry.fire("special_client_list", {
status: "error",
error_msg: tr("Query timeout")
});
}, 5000);
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
event_registry.on("special_client_list", event => clearTimeout(query_timeout));
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* first time client list show */
{
let shown;
event_registry.on('show_client_list', event => {
if(shown) return;
shown = true;
event_registry.fire("query_special_clients");
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* the client list filter */
{
let filter;
const overlay = container.find(".overlay-filter-no-result");
const update_filter = () => {
let shown = 0, hidden = 0;
container_entries.find(".client").each(function () {
const text = this.getAttribute("x-filter");
if(!filter || text.toLowerCase().indexOf(filter) != -1) {
this.classList.remove("hidden");
shown++;
} else {
this.classList.add("hidden");
hidden++;
}
});
if(shown == 0 && hidden == 0) return;
overlay.toggleClass("hidden", shown != 0);
};
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("special_client_list", event => update_filter());
event_registry.on("filter_client_list", event => {
filter = (event.filter || "").toLowerCase();
update_filter();
2020-02-22 14:30:17 +01:00
});
}
2020-03-30 13:44:18 +02:00
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("special_client_set", event => {
container.toggleClass("hidden", !!event.client);
event_registry.fire("hide_client_list");
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* the client info */
{
const container = tag.find(".table-head .column-client-specific .client-info");
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
container.find(".button-client-deselect").on("click", event => {
event_registry.fire("special_client_set", { client: undefined });
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("special_client_set", event => {
container.toggleClass("hidden", !event.client);
const client_container = container.find(".container-selected-client");
client_container.find(".htmltag-client").remove();
if(event.client) {
client_container.append(htmltags.generate_client_object({
client_unique_id: event.client.unique_id,
client_name: event.client.name,
client_id: 0,
client_database_id: event.client.database_id,
add_braces: false
}));
}
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const power_needed_map = {
i_client_music_rename_power: "i_client_music_needed_rename_power",
i_client_music_modify_power: "i_client_music_needed_modify_power",
i_client_music_delete_power: "i_client_music_needed_delete_power",
i_playlist_view_power: "i_playlist_needed_view_power",
i_playlist_modify_power: "i_playlist_needed_modify_power",
i_playlist_permission_modify_power: "i_playlist_needed_permission_modify_power",
i_playlist_song_add_power: "i_playlist_song_needed_add_power",
i_playlist_song_move_power: "i_playlist_song_needed_move_power",
i_playlist_song_remove_power: "i_playlist_song_needed_remove_power",
b_virtualserver_playlist_permission_list: "b_virtualserver_playlist_permission_list"
};
const needed_power_map = Object.entries(power_needed_map).reduce((ret, entry) => {
const [key, value] = entry;
ret[value] = key;
return ret;
}, {});
/* general permissions */
{
/* permission input functionality */
{
tag.find(".general-permission").each((_, _e) => {
const elem = $(_e) as JQuery<HTMLDivElement>;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const permission_name = elem.attr("x-permission");
if(!permission_name) return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const input = elem.find("input");
input.attr("maxlength", 6);
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
let last_sync_value = undefined;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_general_permissions", event => {
input.prop("disabled", true).val(null);
input.attr("placeholder", tr("loading..."));
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("general_permissions", event => {
input.prop("disabled", true).val(null);
if(event.status === "timeout") {
input.attr("placeholder", tr("load timeout"));
} else if(event.status === "success") {
input.prop("disabled", false); //TODO: Check permissions?
input.attr("placeholder", null);
const value = event.permissions ? event.permissions[permission_name] || 0 : 0;
last_sync_value = value;
input.val(value);
} else {
input.attr("placeholder", event.error_msg || tr("load error"));
}
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_general_permission_result", event => {
if(event.key !== permission_name) return;
input.prop("disabled", false); //TODO: Check permissions?
input.attr("placeholder", null);
if(event.status === "success") {
input.val(event.value);
last_sync_value = event.value;
} else if(event.status === "error") {
if(typeof last_sync_value === "number") input.val(last_sync_value);
createErrorModal(tr("Failed to change permission"), tra("Failed to change permission:{:br:}{}", event.error_msg)).open();
}
});
input.on("focusout", event => {
if(input.prop("disabled")) return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const value = parseInt(input.val() as string);
if(value === last_sync_value) return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input.prop("disabled", true).val(null);
input.attr("placeholder", tr("applying..."));
event_registry.fire("set_general_permission", {
key: permission_name,
value: value || 0
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
input.on("keyup", event => event.key === "Enter" && input.blur());
2020-02-22 14:30:17 +01:00
});
}
2020-03-30 13:44:18 +02:00
/* the tooltip functionality */
2020-02-22 14:30:17 +01:00
{
2020-03-30 13:44:18 +02:00
tag.find(".general-permission").each((_, _e) => {
const elem = $(_e) as JQuery<HTMLDivElement>;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const permission_name = elem.attr("x-permission");
if(!permission_name) return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const required_power = needed_power_map[permission_name];
if(!required_power) return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
let last_sync_value = undefined;
let current_tag: JQuery;
let loading = false;
let query_result: {
status: "error" | "timeout" | "success"
groups?: {
name: string,
value: number,
id: number
}[],
error_msg?: string
};
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("general_permissions", event => {
if(event.status === "success")
last_sync_value = event.permissions ? event.permissions[permission_name] || 0 : 0;
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_general_permission_result", event => {
if(event.key !== permission_name) return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
if(event.status === "success")
last_sync_value = event.value;
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("refresh_permissions", event => {
query_result = undefined; /* require for the next time */
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const show_query_result = () => {
if(!current_tag) return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const container_groups = current_tag.find(".container-groups");
container_groups.children().remove();
current_tag.find(".container-status").addClass("hidden");
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
if(loading) {
current_tag.find(".status-loading").removeClass("hidden");
} else if(!query_result || query_result.status === "error") {
current_tag
.find(".status-error").removeClass("hidden")
.text((query_result ? query_result.error_msg : "") || tr("failed to query data"));
} else if(query_result.status === "timeout") {
current_tag
.find(".status-error").removeClass("hidden")
.text(tr("timeout while loading"));
} else {
let count = 0;
for(const group of (query_result.groups || [])) {
if(group.value !== -1 && group.value < last_sync_value) continue;
count++;
container_groups.append($.spawn("div").addClass("group").text(
" - " + group.name + " (" + group.id + ")"
));
2020-02-22 14:30:17 +01:00
}
2020-03-30 13:44:18 +02:00
if(count === 0) current_tag.find(".status-no-groups").removeClass("hidden");
}
};
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
tooltip.initialize(elem, {
on_show(tag: JQuery<HTMLElement>) {
current_tag = tag;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
if(!query_result && !loading) {
event_registry.fire("query_group_permissions", {
permission_name: required_power
});
loading = true;
}
show_query_result();
},
on_hide(tag: JQuery<HTMLElement>) {
current_tag = undefined;
}
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
event_registry.on("group_permissions", event => {
if(event.permission_name !== required_power) return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
loading = false;
query_result = event;
show_query_result();
});
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* refresh mechanism */
{
event_registry.on("refresh_permissions", event => event_registry.fire("query_general_permissions"));
}
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* permission set timeout */
{
let permission_timers: {[key: string]:any} = {};
event_registry.on("set_general_permission", event => {
if(permission_timers[event.key])
clearTimeout(permission_timers[event.key]);
permission_timers[event.key] = setTimeout(() => {
event_registry.fire("set_general_permission_result", {
key: event.key,
status: "error",
error_msg: tr("controller timeout")
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
}, 5000);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_general_permission_result", event => {
clearTimeout(permission_timers[event.key]);
delete permission_timers[event.key];
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* group query timeout */
{
let timers: {[key: string]:any} = {};
event_registry.on("query_group_permissions", event => {
if(timers[event.permission_name])
clearTimeout(timers[event.permission_name]);
timers[event.permission_name] = setTimeout(() => {
event_registry.fire("group_permissions", {
permission_name: event.permission_name,
status: "timeout"
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
}, 5000);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("group_permissions", event => {
clearTimeout(timers[event.permission_name]);
delete timers[event.permission_name];
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* query timeout */
{
let query_timeout;
event_registry.on("query_general_permissions", event => {
clearTimeout(query_timeout);
query_timeout = setTimeout(() => {
event_registry.fire("general_permissions", {
status: "timeout"
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
}, 5000);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("general_permissions", event => clearTimeout(query_timeout));
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* refresh button */
{
const button = tag.find(".button-permission-refresh");
let refresh_timer;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
let loading_client_permissions = false;
let loading_general_permissions = false;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const update_button = () =>
button.prop("disabled", refresh_timer || loading_client_permissions || loading_general_permissions);
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_general_permissions", event => {
loading_general_permissions = true;
update_button();
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("general_permissions", event => {
loading_general_permissions = false;
update_button();
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("query_client_permissions", event => {
loading_client_permissions = true;
update_button();
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("client_permissions", event => {
loading_client_permissions = false;
update_button();
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
button.on('click', event => {
event_registry.fire("refresh_permissions");
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* allow refreshes only every second */
refresh_timer = setTimeout(() => {
refresh_timer = undefined;
2020-02-22 14:30:17 +01:00
update_button();
2020-03-30 13:44:18 +02:00
}, 1000);
});
2020-02-22 14:30:17 +01:00
}
2020-03-30 13:44:18 +02:00
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* client specific permissions */
{
const container = tag.find(".column-client-specific");
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
let client_database_id = 0;
let needed_permissions: {[key: string]:number} = {};
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* needed permissions updater */
{
event_registry.on("general_permissions", event => {
if(event.status !== "success") return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
needed_permissions = event.permissions;
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_general_permission_result", event => {
if (event.status !== "success") return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
needed_permissions[event.key] = event.value;
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("special_client_set", event => {
client_database_id = event.client ? event.client.database_id : 0;
container.find(".client-permission").toggleClass("hidden", !event.client);
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
if(client_database_id)
event_registry.fire("query_client_permissions", { client_database_id: client_database_id });
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const enabled_class = "client-apply";
const disabled_class = "client-delete";
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
container.find(".client-permission").each((_, _e) => {
const elem = $(_e);
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const input = elem.find("input");
const status_indicator = elem.find(".icon_em");
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const permission_name = elem.attr("x-permission") as string;
const permission_needed_name = power_needed_map[permission_name];
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
let last_sync_value = undefined;
let hide_indicator = false;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
if(typeof permission_needed_name !== "string") {
log.warn(LogCategory.GENERAL, tr("Missing permission needed mapping for %s"), permission_name);
return;
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const update_indicator = () => {
const value = parseInt(input.val() as string);
const needed = typeof needed_permissions[permission_needed_name] === "number" ? needed_permissions[permission_needed_name] : 0;
const flag = value == -1 ? true : isNaN(value) || value == 0 ? false : value >= needed;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
status_indicator.toggle(!hide_indicator);
status_indicator.toggleClass(enabled_class, flag).toggleClass(disabled_class, !flag);
};
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("special_client_set", event => {
last_sync_value = undefined;
});
event_registry.on("general_permissions", event => update_indicator());
event_registry.on("set_general_permission_result", event => {
if(event.key !== permission_needed_name) return;
if(event.status !== "success") return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
update_indicator();
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* loading the permission */
event_registry.on("query_client_permissions", event => {
if(event.client_database_id !== client_database_id) return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
last_sync_value = undefined;
hide_indicator = true;
input.prop("disabled", true).val(null);
input.attr("placeholder", tr("loading..."));
update_indicator();
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on('client_permissions', event => {
if(event.client_database_id !== client_database_id) return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
hide_indicator = false;
input.prop("disabled", true).val(null);
if(event.status === "timeout") {
input.attr("placeholder", tr("load timeout"));
} else if(event.status === "success") {
input.prop("disabled", false); //TODO: Check permissions?
input.attr("placeholder", null);
const value = event.permissions ? event.permissions[permission_name] || 0 : 0;
last_sync_value = value;
input.val(value);
} else {
input.attr("placeholder", event.error_msg || tr("load error"));
}
update_indicator();
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* permission editing */
input.attr("maxlength", 6);
input.on("focusout", event => {
if(!client_database_id) return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
const value = parseInt(input.val() as string);
if(value === last_sync_value) return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input.prop("disabled", true).val(null);
input.attr("placeholder", tr("applying..."));
event_registry.fire("set_client_permission", {
client_database_id: client_database_id,
key: permission_name,
value: value || 0
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
hide_indicator = true;
update_indicator();
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input.on("change", () => update_indicator());
input.on("keyup", event => event.key === "Enter" && input.blur());
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_client_permission_result", event => {
if(event.key !== permission_name) return;
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
input.prop("disabled", false); //TODO: Check permissions?
input.attr("placeholder", null);
if(event.status === "success") {
input.val(event.value);
last_sync_value = event.value;
} else if(event.status === "error") {
if(typeof last_sync_value === "number") input.val(last_sync_value);
createErrorModal(tr("Failed to change permission"), tra("Failed to change permission:{:br:}{}", event.error_msg)).open();
}
hide_indicator = false;
update_indicator();
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* client permission query timeout */
{
let timeout: {[key: number]: any} = {};
event_registry.on("query_client_permissions", event => {
if(timeout[event.client_database_id])
2020-02-22 14:30:17 +01:00
clearTimeout(timeout[event.client_database_id]);
2020-03-30 13:44:18 +02:00
timeout[event.client_database_id] = setTimeout(() => {
event_registry.fire("client_permissions", {
status: "timeout",
client_database_id: event.client_database_id
});
}, 5000);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("client_permissions", event => {
clearTimeout(timeout[event.client_database_id]);
});
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* client permission set timeout */
{
let timeout: {[key: string]: any} = {};
event_registry.on("set_client_permission", event => {
const key = event.client_database_id + "_" + event.key;
if(timeout[key])
clearTimeout(timeout[key]);
timeout[key] = setTimeout(() => {
event_registry.fire("set_client_permission_result", {
key: event.key,
status: "error",
client_database_id: event.client_database_id,
error_msg: tr("timeout")
});
}, 5000);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
event_registry.on("set_client_permission_result", event => {
const key = event.client_database_id + "_" + event.key;
if(timeout[key]) {
clearTimeout(timeout[key]);
delete timeout[key];
}
2020-02-22 14:30:17 +01:00
});
}
2020-03-30 13:44:18 +02:00
event_registry.on("refresh_permissions", event => {
if(client_database_id)
event_registry.fire("query_client_permissions", { client_database_id: client_database_id });
2020-02-22 14:30:17 +01:00
});
2020-03-30 13:44:18 +02:00
tooltip.initialize(container);
}
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* a title attribute for permission column */
tag.find(".table-body .column-permission a").each(function () {
this.setAttribute("title", this.textContent);
});
2020-02-22 14:30:17 +01:00
2020-03-30 13:44:18 +02:00
/* initialize on show */
{
let initialized = false;
event_registry.on("show_container", event => {
if(event.container !== "permissions" || initialized) return;
initialized = true;
event_registry.fire("special_client_set", { client: undefined });
event_registry.fire("query_general_permissions", {});
});
2020-02-22 14:30:17 +01:00
}
}