Add proper handling for dev/patron status on dashboard

This commit is contained in:
NovaFox161
2020-05-26 21:50:33 -05:00
parent 7683d6fd8d
commit 9b7d57034b
2 changed files with 610 additions and 586 deletions

View File

@@ -9,198 +9,205 @@ import {GuildSettingsUpdateRequest} from "@/network/guild/settings/GuildSettings
import {WebGuildUpdateRequest} from "@/network/guild/WebGuildUpdateRequest";
export class DashboardGuildRunner implements TaskCallback {
guild: WebGuild = new WebGuild("");
guild: WebGuild = new WebGuild("");
apiUrl: string;
apiKey: string;
apiUrl: string;
apiKey: string;
guildId: string;
userId: string;
guildId: string;
userId: string;
constructor(apiKey: string, apiUrl: string, userId: string) {
this.apiKey = apiKey;
this.apiUrl = apiUrl;
this.userId = userId;
constructor(apiKey: string, apiUrl: string, userId: string) {
this.apiKey = apiKey;
this.apiUrl = apiUrl;
this.userId = userId;
this.guildId = window.location.pathname.split("/")[2];
}
this.guildId = window.location.pathname.split("/")[2];
}
start() {
//First thing we need to do is load the web guild data so we can display it for editing.
let wgr = new WebGuildGetRequest(this.guildId, this.userId, this);
wgr.provideApiDetails(this.apiKey, this.apiUrl);
start() {
//First thing we need to do is load the web guild data so we can display it for editing.
let wgr = new WebGuildGetRequest(this.guildId, this.userId, this);
wgr.provideApiDetails(this.apiKey, this.apiUrl);
wgr.execute();
}
wgr.execute();
}
private handleWebGuildGet(status: NetworkCallStatus) {
this.guild = new WebGuild(this.guildId).fromJson(status.body);
private handleWebGuildGet(status: NetworkCallStatus) {
this.guild = new WebGuild(this.guildId).fromJson(status.body);
//load in settings data
(<HTMLInputElement>document.getElementById("nickname-input")).value = this.guild.botNick;
document.getElementById("nick-update-btn")!.onclick = function () {
this.updateBotNick();
}.bind(this);
if (!this.guild.settings.isDevGuild || !this.guild.settings.isPatronGuild) {
ElementUtil.hideLoader();
document.getElementById("not-patron-guild")!.hidden = false;
Snackbar.showSnackbar("Guild is not a patron guild!");
return;
}
(<HTMLInputElement>document.getElementById("prefix-input")).value = this.guild.settings.prefix;
document.getElementById("prefix-update-btn")!.onclick = function () {
this.updatePrefix();
}.bind(this);
//load in settings data
(<HTMLInputElement>document.getElementById("nickname-input")).value = this.guild.botNick;
document.getElementById("nick-update-btn")!.onclick = function () {
this.updateBotNick();
}.bind(this);
let controlRoleSelect = document.getElementById("control-role-select")!;
for (let i = 0; i < this.guild.roles.length; i++) {
let role = this.guild.roles[i];
let opt = document.createElement("option");
(<HTMLInputElement>document.getElementById("prefix-input")).value = this.guild.settings.prefix;
document.getElementById("prefix-update-btn")!.onclick = function () {
this.updatePrefix();
}.bind(this);
opt.innerHTML = role.name;
opt.value = role.id.toString();
opt.selected = role.id.toString() == this.guild.settings.controlRole;
let controlRoleSelect = document.getElementById("control-role-select")!;
for (let i = 0; i < this.guild.roles.length; i++) {
let role = this.guild.roles[i];
let opt = document.createElement("option");
controlRoleSelect.appendChild(opt);
}
document.getElementById("control-role-update-btn")!.onclick = function () {
this.updateControlRole();
}.bind(this);
opt.innerHTML = role.name;
opt.value = role.id.toString();
opt.selected = role.id.toString() == this.guild.settings.controlRole;
let chanSelect = document.getElementById("discal-chan-select")!;
for (let i = 0; i < this.guild.channels.length; i++) {
let chan = this.guild.channels[i];
let opt = document.createElement("option");
controlRoleSelect.appendChild(opt);
}
document.getElementById("control-role-update-btn")!.onclick = function () {
this.updateControlRole();
}.bind(this);
opt.innerHTML = chan.name;
opt.value = chan.id.toString();
if (chan.id == "0" && this.guild.settings.disCalChannel === "all") {
opt.selected = true;
} else {
opt.selected = chan.id.toString() == this.guild.settings.disCalChannel;
}
chanSelect.appendChild(opt);
}
document.getElementById("discal-chan-update-btn")!.onclick = function () {
this.updateDiscalChannel();
}.bind(this);
let chanSelect = document.getElementById("discal-chan-select")!;
for (let i = 0; i < this.guild.channels.length; i++) {
let chan = this.guild.channels[i];
let opt = document.createElement("option");
let langSelect = document.getElementById("discal-lang-select")!;
for (let i = 0; i < this.guild.availableLangs.length; i++) {
let lang = this.guild.availableLangs[i];
let opt = document.createElement("option");
opt.innerHTML = chan.name;
opt.value = chan.id.toString();
if (chan.id == "0" && this.guild.settings.disCalChannel === "all") {
opt.selected = true;
} else {
opt.selected = chan.id.toString() == this.guild.settings.disCalChannel;
}
chanSelect.appendChild(opt);
}
document.getElementById("discal-chan-update-btn")!.onclick = function () {
this.updateDiscalChannel();
}.bind(this);
opt.innerHTML = lang.toUpperCase();
opt.value = lang.toUpperCase();
let langSelect = document.getElementById("discal-lang-select")!;
for (let i = 0; i < this.guild.availableLangs.length; i++) {
let lang = this.guild.availableLangs[i];
let opt = document.createElement("option");
opt.selected = lang.toUpperCase() == this.guild.settings.lang.toUpperCase();
langSelect.appendChild(opt);
}
document.getElementById("discal-lang-update-btn")!.onclick = function () {
this.updateLang();
}.bind(this);
opt.innerHTML = lang.toUpperCase();
opt.value = lang.toUpperCase();
opt.selected = lang.toUpperCase() == this.guild.settings.lang.toUpperCase();
langSelect.appendChild(opt);
}
document.getElementById("discal-lang-update-btn")!.onclick = function () {
this.updateLang();
}.bind(this);
//load data that cannot be edited
(<HTMLParagraphElement>document.getElementById("shard-display")).innerHTML = "Shard: " + this.guild.shard;
//load data that cannot be edited
(<HTMLParagraphElement>document.getElementById("shard-display")).innerHTML = "Shard: " + this.guild.shard;
if (this.guild.settings.isPatronGuild) {
(<HTMLParagraphElement>document.getElementById("patron-display")).innerHTML = "This guild is a patron guild";
} else {
(<HTMLParagraphElement>document.getElementById("patron-display")).innerHTML = "This guild is NOT a patron guild";
}
if (this.guild.settings.isDevGuild) {
(<HTMLParagraphElement>document.getElementById("dev-display")).innerHTML = "This guild is a dev guild";
} else {
(<HTMLParagraphElement>document.getElementById("dev-display")).innerHTML = "This guild is NOT a dev guild";
}
//display what shard the server is on when we support that...
if (this.guild.settings.isPatronGuild) {
(<HTMLParagraphElement>document.getElementById("patron-display")).innerHTML = "This guild is a patron guild";
} else {
(<HTMLParagraphElement>document.getElementById("patron-display")).innerHTML = "This guild is NOT a patron guild";
}
if (this.guild.settings.isDevGuild) {
(<HTMLParagraphElement>document.getElementById("dev-display")).innerHTML = "This guild is a dev guild";
} else {
(<HTMLParagraphElement>document.getElementById("dev-display")).innerHTML = "This guild is NOT a dev guild";
}
//display what shard the server is on when we support that...
//Hide loader and show the data container...
ElementUtil.hideLoader();
document.getElementById("guild-settings")!.hidden = false;
document.getElementById("guild-data")!.hidden = false;
}
//Hide loader and show the data container...
ElementUtil.hideLoader();
document.getElementById("guild-settings")!.hidden = false;
document.getElementById("guild-data")!.hidden = false;
}
private updateBotNick() {
let request = new WebGuildUpdateRequest(this.guildId, this);
request.provideApiDetails(this.apiKey, this.apiUrl);
private updateBotNick() {
let request = new WebGuildUpdateRequest(this.guildId, this);
request.provideApiDetails(this.apiKey, this.apiUrl);
request.botNick = (<HTMLInputElement>document.getElementById("nickname-input")).value;
this.guild.botNick = (<HTMLInputElement>document.getElementById("nickname-input")).value;
request.botNick = (<HTMLInputElement>document.getElementById("nickname-input")).value;
this.guild.botNick = (<HTMLInputElement>document.getElementById("nickname-input")).value;
request.execute();
}
request.execute();
}
private updatePrefix() {
let request = new GuildSettingsUpdateRequest(this.guildId, this);
request.provideApiDetails(this.apiKey, this.apiUrl);
private updatePrefix() {
let request = new GuildSettingsUpdateRequest(this.guildId, this);
request.provideApiDetails(this.apiKey, this.apiUrl);
request.prefix = (<HTMLInputElement>document.getElementById("prefix-input")).value;
this.guild.settings.prefix = request.prefix;
request.prefix = (<HTMLInputElement>document.getElementById("prefix-input")).value;
this.guild.settings.prefix = request.prefix;
request.execute();
}
request.execute();
}
private updateControlRole() {
let request = new GuildSettingsUpdateRequest(this.guildId, this);
request.provideApiDetails(this.apiKey, this.apiUrl);
private updateControlRole() {
let request = new GuildSettingsUpdateRequest(this.guildId, this);
request.provideApiDetails(this.apiKey, this.apiUrl);
let select = <HTMLSelectElement>document.getElementById("control-role-select");
request.controlRole = select.selectedOptions[0].value;
this.guild.settings.controlRole = request.controlRole;
let select = <HTMLSelectElement>document.getElementById("control-role-select");
request.controlRole = select.selectedOptions[0].value;
this.guild.settings.controlRole = request.controlRole;
request.execute();
}
request.execute();
}
private updateDiscalChannel() {
let request = new GuildSettingsUpdateRequest(this.guildId, this);
request.provideApiDetails(this.apiKey, this.apiUrl);
private updateDiscalChannel() {
let request = new GuildSettingsUpdateRequest(this.guildId, this);
request.provideApiDetails(this.apiKey, this.apiUrl);
let select = <HTMLSelectElement>document.getElementById("discal-chan-select");
request.discalChannel = select.selectedOptions[0].value;
this.guild.settings.disCalChannel = request.discalChannel;
let select = <HTMLSelectElement>document.getElementById("discal-chan-select");
request.discalChannel = select.selectedOptions[0].value;
this.guild.settings.disCalChannel = request.discalChannel;
request.execute();
}
request.execute();
}
private updateLang() {
let request = new GuildSettingsUpdateRequest(this.guildId, this);
request.provideApiDetails(this.apiKey, this.apiUrl);
private updateLang() {
let request = new GuildSettingsUpdateRequest(this.guildId, this);
request.provideApiDetails(this.apiKey, this.apiUrl);
let select = <HTMLSelectElement>document.getElementById("discal-lang-select");
request.lang = select.selectedOptions[0].value;
this.guild.settings.lang = request.lang;
let select = <HTMLSelectElement>document.getElementById("discal-lang-select");
request.lang = select.selectedOptions[0].value;
this.guild.settings.lang = request.lang;
request.execute();
}
request.execute();
}
onCallback(status: NetworkCallStatus): void {
if (status.isSuccess) {
switch (status.type) {
case TaskType.WEB_GUILD_GET:
this.handleWebGuildGet(status);
break;
case TaskType.GUILD_SETTINGS_UPDATE:
Snackbar.showSnackbar(status.message);
break;
case TaskType.WEB_GUILD_UPDATE:
Snackbar.showSnackbar(status.message);
break;
default:
break;
}
} else {
switch (status.type) {
case TaskType.WEB_GUILD_GET:
if (status.code == 404) {
ElementUtil.hideLoader();
document.getElementById("not-connected")!.hidden = false;
Snackbar.showSnackbar("Guild not Found");
} else {
Snackbar.showSnackbar("[ERROR] " + status.message);
}
break;
default:
Snackbar.showSnackbar("[ERROR] " + status.message);
break;
}
}
}
onCallback(status: NetworkCallStatus): void {
if (status.isSuccess) {
switch (status.type) {
case TaskType.WEB_GUILD_GET:
this.handleWebGuildGet(status);
break;
case TaskType.GUILD_SETTINGS_UPDATE:
Snackbar.showSnackbar(status.message);
break;
case TaskType.WEB_GUILD_UPDATE:
Snackbar.showSnackbar(status.message);
break;
default:
break;
}
} else {
switch (status.type) {
case TaskType.WEB_GUILD_GET:
if (status.code == 404) {
ElementUtil.hideLoader();
document.getElementById("not-connected")!.hidden = false;
Snackbar.showSnackbar("Guild not Found");
} else {
Snackbar.showSnackbar("[ERROR] " + status.message);
}
break;
default:
Snackbar.showSnackbar("[ERROR] " + status.message);
break;
}
}
}
}

View File

@@ -2,524 +2,541 @@
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<!--Meta Stuffs-->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="The Ultimate Discord Calendar Bot">
<!--Meta Stuffs-->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="The Ultimate Discord Calendar Bot">
<meta property="og:title" content="DisCal"/>
<meta property="og:url" content="https://www.discalbot.com"/>
<meta property="og:description" content="The Ultimate Discord Calendar Bot"/>
<meta property="og:image" content="/assets/images/logos/Dark/Opaque/Logo%20Dark%20+bg.png">
<meta property="og:title" content="DisCal"/>
<meta property="og:url" content="https://www.discalbot.com"/>
<meta property="og:description" content="The Ultimate Discord Calendar Bot"/>
<meta property="og:image" content="/assets/images/logos/Dark/Opaque/Logo%20Dark%20+bg.png">
<!-- ****** faviconit.com favicons ****** -->
<link rel="shortcut icon" href="/assets/img/favicon/favicon.ico">
<link rel="icon" sizes="16x16 32x32 64x64" href="/assets/img/favicon.ico">
<link rel="icon" type="image/png" sizes="196x196" href="/assets/img/favicon/favicon-192.png">
<link rel="icon" type="image/png" sizes="160x160" href="/assets/img/favicon/favicon-160.png">
<link rel="icon" type="image/png" sizes="96x96" href="/assets/img/favicon/favicon-96.png">
<link rel="icon" type="image/png" sizes="64x64" href="/assets/img/favicon/favicon-64.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/img/favicon/favicon-32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/img/favicon/favicon-16.png">
<link rel="apple-touch-icon" href="/assets/img/favicon/favicon-57.png">
<link rel="apple-touch-icon" sizes="114x114" href="/assets/img/favicon/favicon-114.png">
<link rel="apple-touch-icon" sizes="72x72" href="/assets/img/favicon/favicon-72.png">
<link rel="apple-touch-icon" sizes="144x144" href="/assets/img/favicon/favicon-144.png">
<link rel="apple-touch-icon" sizes="60x60" href="/assets/img/favicon/favicon-60.png">
<link rel="apple-touch-icon" sizes="120x120" href="/assets/img/favicon/favicon-120.png">
<link rel="apple-touch-icon" sizes="76x76" href="/assets/img/favicon/favicon-76.png">
<link rel="apple-touch-icon" sizes="152x152" href="/assets/img/favicon/favicon-152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/assets/img/favicon/favicon-180.png">
<meta name="msapplication-TileColor" content="#FFFFFF">
<meta name="msapplication-TileImage" content="/assets/img/favicon/favicon-144.png">
<meta name="msapplication-config" content="/assets/img/favicon/browserconfig.xml">
<!-- ****** faviconit.com favicons ****** -->
<!-- ****** faviconit.com favicons ****** -->
<link rel="shortcut icon" href="/assets/img/favicon/favicon.ico">
<link rel="icon" sizes="16x16 32x32 64x64" href="/assets/img/favicon.ico">
<link rel="icon" type="image/png" sizes="196x196" href="/assets/img/favicon/favicon-192.png">
<link rel="icon" type="image/png" sizes="160x160" href="/assets/img/favicon/favicon-160.png">
<link rel="icon" type="image/png" sizes="96x96" href="/assets/img/favicon/favicon-96.png">
<link rel="icon" type="image/png" sizes="64x64" href="/assets/img/favicon/favicon-64.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/img/favicon/favicon-32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/img/favicon/favicon-16.png">
<link rel="apple-touch-icon" href="/assets/img/favicon/favicon-57.png">
<link rel="apple-touch-icon" sizes="114x114" href="/assets/img/favicon/favicon-114.png">
<link rel="apple-touch-icon" sizes="72x72" href="/assets/img/favicon/favicon-72.png">
<link rel="apple-touch-icon" sizes="144x144" href="/assets/img/favicon/favicon-144.png">
<link rel="apple-touch-icon" sizes="60x60" href="/assets/img/favicon/favicon-60.png">
<link rel="apple-touch-icon" sizes="120x120" href="/assets/img/favicon/favicon-120.png">
<link rel="apple-touch-icon" sizes="76x76" href="/assets/img/favicon/favicon-76.png">
<link rel="apple-touch-icon" sizes="152x152" href="/assets/img/favicon/favicon-152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/assets/img/favicon/favicon-180.png">
<meta name="msapplication-TileColor" content="#FFFFFF">
<meta name="msapplication-TileImage" content="/assets/img/favicon/favicon-144.png">
<meta name="msapplication-config" content="/assets/img/favicon/browserconfig.xml">
<!-- ****** faviconit.com favicons ****** -->
<title>DisCal - Dashboard</title>
<title>DisCal - Dashboard</title>
<!-- Custom fonts for this template-->
<link href="/vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom fonts for this template-->
<link href="/vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="/assets/css/sb-admin-2.min.css" rel="stylesheet">
<!-- Custom styles for this template-->
<link href="/assets/css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body id="page-top" th:data-api-key="${key}" th:data-api-url="${api_url}" th:data-user-id="${id}"
data-dashboard="guild">
data-dashboard="guild">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-discal-dark-gray sidebar sidebar-dark accordion"
id="accordionSidebar">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-discal-dark-gray sidebar sidebar-dark accordion"
id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="/">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-calendar"></i>
</div>
<div class="sidebar-brand-text mx-3">DISCAL</div>
</a>
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="/">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-calendar"></i>
</div>
<div class="sidebar-brand-text mx-3">DISCAL</div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - About -->
<li class="nav-item">
<a class="nav-link" href="/about">
<i class="fas fa-fw fa-info-circle"></i>
<span>About</span></a>
</li>
<!-- Nav Item - About -->
<li class="nav-item">
<a class="nav-link" href="/about">
<i class="fas fa-fw fa-info-circle"></i>
<span>About</span></a>
</li>
<!-- Nav Item - Commands -->
<li class="nav-item">
<a class="nav-link" href="/commands">
<i class="fas fa-fw fa-terminal"></i>
<span>Commands</span></a>
</li>
<!-- Nav Item - Commands -->
<li class="nav-item">
<a class="nav-link" href="/commands">
<i class="fas fa-fw fa-terminal"></i>
<span>Commands</span></a>
</li>
<!-- Nav Item - Setup -->
<li class="nav-item">
<a class="nav-link" href="/setup">
<i class="fas fa-fw fa-cog"></i>
<span>Setup</span></a>
</li>
<!-- Nav Item - Setup -->
<li class="nav-item">
<a class="nav-link" href="/setup">
<i class="fas fa-fw fa-cog"></i>
<span>Setup</span></a>
</li>
<!-- Nav Item - Lazy DisCal -->
<li class="nav-item">
<a class="nav-link" href="/lazy-discal">
<i class="fas fa-fw fa-magic"></i>
<span>Lazy DisCal</span></a>
</li>
<!-- Nav Item - Lazy DisCal -->
<li class="nav-item">
<a class="nav-link" href="/lazy-discal">
<i class="fas fa-fw fa-magic"></i>
<span>Lazy DisCal</span></a>
</li>
<!-- Nav Item - Status -->
<li class="nav-item">
<a class="nav-link" href="/status">
<i class="fas fa-fw fa-info-circle"></i>
<span>Status</span></a>
</li>
<!-- Nav Item - Status -->
<li class="nav-item">
<a class="nav-link" href="/status">
<i class="fas fa-fw fa-info-circle"></i>
<span>Status</span></a>
</li>
<!-- Nav Item - Dashboard -->
<li class="nav-item active">
<a class="nav-link" href="/dashboard">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Nav Item - Dashboard -->
<li class="nav-item active">
<a class="nav-link" href="/dashboard">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Modules list (only displayed if logged in) -->
<div th:if="${logged_in}">
<!-- Heading -->
<div class="sidebar-heading">
Modules
</div>
<!-- Modules list (only displayed if logged in) -->
<div th:if="${logged_in}">
<!-- Heading -->
<div class="sidebar-heading">
Modules
</div>
<!-- Start Nav Item - Guild Overview Container -->
<div class="nav-item active">
<a class="nav-link" id="dash-overview-select"
th:href="'/dashboard/' + ${#strings.listSplit(#httpServletRequest.requestURI, '/').get(1)}">
<i class="fas fa-fw fa-book-open"></i>
<span>Guild Overview</span>
</a>
</div>
<!-- End Nav Item - Guild Overview Container -->
<!-- Start Nav Item - Guild Overview Container -->
<div class="nav-item active">
<a class="nav-link" id="dash-overview-select"
th:href="'/dashboard/' + ${#strings.listSplit(#httpServletRequest.requestURI, '/').get(1)}">
<i class="fas fa-fw fa-book-open"></i>
<span>Guild Overview</span>
</a>
</div>
<!-- End Nav Item - Guild Overview Container -->
<!-- Start Nav Item - Guild Calendar Container -->
<div class="nav-item">
<a class="nav-link" id="dash-calendar-select"
th:href="'/dashboard/' + ${#strings.listSplit(#httpServletRequest.requestURI, '/').get(1)} + '/calendar'">
<i class="fas fa-fw fa-calendar-alt"></i>
<span>Calendar</span>
</a>
</div>
<!-- End Nav Item - Guild Calendar Container -->
<!-- Start Nav Item - Guild Calendar Container -->
<div class="nav-item">
<a class="nav-link" id="dash-calendar-select"
th:href="'/dashboard/' + ${#strings.listSplit(#httpServletRequest.requestURI, '/').get(1)} + '/calendar'">
<i class="fas fa-fw fa-calendar-alt"></i>
<span>Calendar</span>
</a>
</div>
<!-- End Nav Item - Guild Calendar Container -->
<!-- Start Nav Item - Guild Events Container -->
<div class="nav-item">
<a class="nav-link" id="dash-events-select"
th:href="'/dashboard/' + ${#strings.listSplit(#httpServletRequest.requestURI, '/').get(1)} + '/events'">
<i class="fas fa-fw fa-calendar-day"></i>
<span>Events</span>
</a>
</div>
<!-- End Nav Item - Guild Events Container -->
<!-- Start Nav Item - Guild Events Container -->
<div class="nav-item">
<a class="nav-link" id="dash-events-select"
th:href="'/dashboard/' + ${#strings.listSplit(#httpServletRequest.requestURI, '/').get(1)} + '/events'">
<i class="fas fa-fw fa-calendar-day"></i>
<span>Events</span>
</a>
</div>
<!-- End Nav Item - Guild Events Container -->
<!-- Start Nav Item - Guild Announcements Container -->
<div class="nav-item">
<a class="nav-link" id="dash-ann-select"
th:href="'/dashboard/' + ${#strings.listSplit(#httpServletRequest.requestURI, '/').get(1)} + '/announcements'">
<i class="fas fa-fw fa-bell"></i>
<span>Announcements</span>
</a>
</div>
<!-- End Nav Item - Guild Announcements Container -->
<!-- Start Nav Item - Guild Announcements Container -->
<div class="nav-item">
<a class="nav-link" id="dash-ann-select"
th:href="'/dashboard/' + ${#strings.listSplit(#httpServletRequest.requestURI, '/').get(1)} + '/announcements'">
<i class="fas fa-fw fa-bell"></i>
<span>Announcements</span>
</a>
</div>
<!-- End Nav Item - Guild Announcements Container -->
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
</div>
<!-- End Modules list -->
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
</div>
<!-- End Modules list -->
<!-- Guilds list (only displayed if logged in) -->
<div th:if="${logged_in}">
<!-- Heading-->
<div class="sidebar-heading">
Guilds
</div>
<!-- Guilds list (only displayed if logged in) -->
<div th:if="${logged_in}">
<!-- Heading-->
<div class="sidebar-heading">
Guilds
</div>
<!-- Start Nav Item - Guild Container -->
<th:block th:each="guild : ${guilds}">
<th:block th:if="${#strings.contains(#httpServletRequest.requestURI, guild.id)}">
<div class="nav-item active">
<a class="nav-link" th:href="'/dashboard/' + ${guild.id}">
<i class="fas fa-fw fa-chart-area"></i>
<span th:text="${guild.name}"></span>
</a>
</div>
</th:block>
<!-- Start Nav Item - Guild Container -->
<th:block th:each="guild : ${guilds}">
<th:block th:if="${#strings.contains(#httpServletRequest.requestURI, guild.id)}">
<div class="nav-item active">
<a class="nav-link" th:href="'/dashboard/' + ${guild.id}">
<i class="fas fa-fw fa-chart-area"></i>
<span th:text="${guild.name}"></span>
</a>
</div>
</th:block>
<th:block
th:unless="${#strings.contains(#httpServletRequest.requestURI, guild.id)}">
<div class="nav-item">
<a class="nav-link" th:href="'/dashboard/' + ${guild.id}">
<i class="fas fa-fw fa-chart-area"></i>
<span th:text="${guild.name}"></span>
</a>
</div>
</th:block>
</th:block>
<!-- End Nav Item - Guild Container -->
<th:block
th:unless="${#strings.contains(#httpServletRequest.requestURI, guild.id)}">
<div class="nav-item">
<a class="nav-link" th:href="'/dashboard/' + ${guild.id}">
<i class="fas fa-fw fa-chart-area"></i>
<span th:text="${guild.name}"></span>
</a>
</div>
</th:block>
</th:block>
<!-- End Nav Item - Guild Container -->
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
</div>
<!-- End Guilds list -->
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
</div>
<!-- End Guilds list -->
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column bg-discal-not-black">
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column bg-discal-not-black">
<!-- Main Content -->
<div id="content">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-dark bg-discal-blue topbar mb-4 static-top shadow">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-dark bg-discal-blue topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars text-discord-full-white"></i>
</button>
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars text-discord-full-white"></i>
</button>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Support Link -->
<li class="nav-item">
<a class="nav-link text-discord-full-white" th:href="${support_invite}"
target="_blank">
<i class="fas fa-question-circle fa-sm fa-fw mr-2"></i>
Support
</a>
</li>
<!-- Nav Item - Support Link -->
<li class="nav-item">
<a class="nav-link text-discord-full-white" th:href="${support_invite}"
target="_blank">
<i class="fas fa-question-circle fa-sm fa-fw mr-2"></i>
Support
</a>
</li>
<!-- Nav Item - Patreon Link -->
<li class="nav-item">
<a class="nav-link text-discord-full-white"
href="https://www.patreon.com/Novafox" target="_blank">
<i class="fab fa-patreon fa-sm fa-fw mr-2"></i>
Patreon
</a>
</li>
<!-- Nav Item - Patreon Link -->
<li class="nav-item">
<a class="nav-link text-discord-full-white"
href="https://www.patreon.com/Novafox" target="_blank">
<i class="fab fa-patreon fa-sm fa-fw mr-2"></i>
Patreon
</a>
</li>
<!-- Nav Item - Invite Link -->
<li class="nav-item">
<a class="nav-link text-discord-full-white" th:href="${bot_invite}"
target="_blank">
<i class="fas fa-envelope-open-text fa-sm fa-fw mr-2"></i>
Invite
</a>
</li>
<!-- Nav Item - Invite Link -->
<li class="nav-item">
<a class="nav-link text-discord-full-white" th:href="${bot_invite}"
target="_blank">
<i class="fas fa-envelope-open-text fa-sm fa-fw mr-2"></i>
Invite
</a>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li th:if="${logged_in}" class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-lg-inline small" th:text="${username}"></span>
<img class="img-profile rounded-circle" th:src="${pfp}"
alt="pfp">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow
<!-- Nav Item - User Information -->
<li th:if="${logged_in}" class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-lg-inline small" th:text="${username}"></span>
<img class="img-profile rounded-circle" th:src="${pfp}"
alt="pfp">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow
animated--grow-in bg-discal-not-black"
aria-labelledby="userDropdown">
<a class="dropdown-item text-discord-full-white" href="#"
data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2"></i>
Logout
</a>
</div>
</li>
<li th:unless="${logged_in}" class="nav-item">
<a class="nav-link text-discord-full-white" href="/login">
<i class="fas fa-sign-in-alt fa-sm fa-fw mr-2"></i>
Login
</a>
</li>
aria-labelledby="userDropdown">
<a class="dropdown-item text-discord-full-white" href="#"
data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2"></i>
Logout
</a>
</div>
</li>
<li th:unless="${logged_in}" class="nav-item">
<a class="nav-link text-discord-full-white" href="/login">
<i class="fas fa-sign-in-alt fa-sm fa-fw mr-2"></i>
Login
</a>
</li>
</ul>
</ul>
</nav>
<!-- End of Topbar -->
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<div class="loader"></div>
<!-- Begin Page Content -->
<div class="container-fluid">
<div class="loader"></div>
<!--Start not connected display-->
<div id="not-connected" hidden="hidden">
<h2 class="text-discal-blue">It seems this guild doesn't have DisCal in it.</h2>
<!--Start not connected display-->
<div id="not-connected" hidden="hidden">
<h2 class="text-discal-blue">It seems this guild doesn't have DisCal in it.</h2>
<a class="bg-discord-blurple btn btn-discord btn-user btn-block text-discord-full-white"
style="margin: 0 auto; max-width: 200px"
target="_blank"
th:href="${bot_invite}">
Add To Discord!
</a>
</div>
<!--End not connected display-->
<a class="bg-discord-blurple btn btn-discord btn-user btn-block text-discord-full-white"
style="margin: 0 auto; max-width: 200px"
target="_blank"
th:href="${bot_invite}">
Add To Discord!
</a>
</div>
<!--End not connected display-->
<!--Start guild settings display-->
<div id="guild-settings" hidden="hidden">
<!--Start nickname form-->
<form id="nickname-form" class="row form-inline pl-3">
<label for="nickname-input" class="sr-only">Nickname</label>
<!--Start not patron/dev guild display-->
<div id="not-patron-guild" hidden="hidden">
<h2 class="text-discal-blue">It seems this guild is not a patron or dev guiild.</h2>
<div class="mb-2 mr-sm-2 input-group">
<div class="input-group-prepend">
<span class="input-group-text">Nickname</span>
</div>
<input type="text" class="form-control" id="nickname-input"
placeholder="DisCal" maxlength="32">
<div class="input-group-append">
<button type="button" class="btn btn-discal-blue"
id="nick-update-btn">
Update
</button>
</div>
</div>
</form>
<!--End nickname form-->
<a class="bg-discord-blurple btn btn-discord btn-user btn-block text-discord-full-white"
style="margin: 0 auto; max-width: 200px"
target="_blank"
href="https://www.patreon.com/Novafox">
Become a patron now!
</a>
<br>
<br>
<p class="text-center text-discord-full-white">
Already a patron? Join the support server and contact Nova, she'll help you get it sorted out!
</p>
</div>
<!--End not patron/dev guild display-->
<!--Start prefix form-->
<form id="prefix-form" class="row form-inline pl-3">
<label for="prefix-input" class="sr-only">Prefix</label>
<!--Start guild settings display-->
<div id="guild-settings" hidden="hidden">
<!--Start nickname form-->
<form id="nickname-form" class="row form-inline pl-3">
<label for="nickname-input" class="sr-only">Nickname</label>
<div class="mb-2 mr-sm-2 input-group">
<div class="input-group-prepend">
<span class="input-group-text">Prefix</span>
</div>
<input type="text" class="form-control" id="prefix-input"
placeholder="!" maxlength="5">
<div class="input-group-append">
<button type="button" class="btn btn-discal-blue"
id="prefix-update-btn">
Update
</button>
</div>
</div>
</form>
<!--End prefix form-->
<div class="mb-2 mr-sm-2 input-group">
<div class="input-group-prepend">
<span class="input-group-text">Nickname</span>
</div>
<input type="text" class="form-control" id="nickname-input"
placeholder="DisCal" maxlength="32">
<div class="input-group-append">
<button type="button" class="btn btn-discal-blue"
id="nick-update-btn">
Update
</button>
</div>
</div>
</form>
<!--End nickname form-->
<!--Start lang form-->
<!--End lang form-->
<br>
<br>
<br>
<br>
<!--Start prefix form-->
<form id="prefix-form" class="row form-inline pl-3">
<label for="prefix-input" class="sr-only">Prefix</label>
<!--Start control role form-->
<form id="control-role-form" class="row form-inline pl-3">
<label for="control-role-select" class="sr-only">Control Role</label>
<div class="mb-2 mr-sm-2 input-group">
<div class="input-group-prepend">
<span class="input-group-text">Prefix</span>
</div>
<input type="text" class="form-control" id="prefix-input"
placeholder="!" maxlength="5">
<div class="input-group-append">
<button type="button" class="btn btn-discal-blue"
id="prefix-update-btn">
Update
</button>
</div>
</div>
</form>
<!--End prefix form-->
<div class="mb-2 mr-sm-2 input-group">
<div class="input-group-prepend">
<span class="input-group-text">Control Role</span>
</div>
<select class="form-control" id="control-role-select"></select>
<div class="input-group-append">
<button type="button" class="btn btn-discal-blue"
id="control-role-update-btn">
Update
</button>
</div>
</div>
</form>
<!--End control role form-->
<!--Start lang form-->
<!--End lang form-->
<br>
<br>
<br>
<br>
<!--Start discal channel form-->
<form id="discal-chan-form" class="row form-inline pl-3">
<label for="discal-chan-select" class="sr-only">DisCal Channel</label>
<!--Start control role form-->
<form id="control-role-form" class="row form-inline pl-3">
<label for="control-role-select" class="sr-only">Control Role</label>
<div class="mb-2 mr-sm-2 input-group">
<div class="input-group-prepend">
<span class="input-group-text">DisCal Channel</span>
</div>
<select class="form-control" id="discal-chan-select"></select>
<div class="input-group-append">
<button type="button" class="btn btn-discal-blue"
id="discal-chan-update-btn">
Update
</button>
</div>
</div>
</form>
<!--End discal channel form-->
<div class="mb-2 mr-sm-2 input-group">
<div class="input-group-prepend">
<span class="input-group-text">Control Role</span>
</div>
<select class="form-control" id="control-role-select"></select>
<div class="input-group-append">
<button type="button" class="btn btn-discal-blue"
id="control-role-update-btn">
Update
</button>
</div>
</div>
</form>
<!--End control role form-->
<br>
<br>
<br>
<br>
<!--Start discal lang form-->
<form id="discal-lang-form" class="row form-inline pl-3">
<label for="discal-lang-select" class="sr-only">DisCal Language</label>
<!--Start discal channel form-->
<form id="discal-chan-form" class="row form-inline pl-3">
<label for="discal-chan-select" class="sr-only">DisCal Channel</label>
<div class="mb-2 mr-sm-2 input-group">
<div class="input-group-prepend">
<span class="input-group-text">DisCal Language</span>
</div>
<select class="form-control" id="discal-lang-select"></select>
<div class="input-group-append">
<button type="button" class="btn btn-discal-blue"
id="discal-lang-update-btn">
Update
</button>
</div>
</div>
</form>
<!--End discal lang form-->
</div>
<!--End guild settings display-->
<div class="mb-2 mr-sm-2 input-group">
<div class="input-group-prepend">
<span class="input-group-text">DisCal Channel</span>
</div>
<select class="form-control" id="discal-chan-select"></select>
<div class="input-group-append">
<button type="button" class="btn btn-discal-blue"
id="discal-chan-update-btn">
Update
</button>
</div>
</div>
</form>
<!--End discal channel form-->
<br>
<hr>
<br>
<br>
<br>
<!--Begin data display and edit-->
<div id="guild-data" hidden="hidden">
<!--Begin shard display-->
<div>
<p id="shard-display" class="text-discord-full-white text-left"></p>
</div>
<!--End shard display-->
<!--Start discal lang form-->
<form id="discal-lang-form" class="row form-inline pl-3">
<label for="discal-lang-select" class="sr-only">DisCal Language</label>
<br>
<br>
<div class="mb-2 mr-sm-2 input-group">
<div class="input-group-prepend">
<span class="input-group-text">DisCal Language</span>
</div>
<select class="form-control" id="discal-lang-select"></select>
<div class="input-group-append">
<button type="button" class="btn btn-discal-blue"
id="discal-lang-update-btn">
Update
</button>
</div>
</div>
</form>
<!--End discal lang form-->
</div>
<!--End guild settings display-->
<br>
<hr>
<br>
<!--Begin data display and edit-->
<div id="guild-data" hidden="hidden">
<!--Begin shard display-->
<div>
<p id="shard-display" class="text-discord-full-white text-left"></p>
</div>
<!--End shard display-->
<br>
<br>
<!--Begin patron display-->
<div>
<p id="patron-display" class="text-discord-full-white text-left"></p>
</div>
<!--End patron display-->
<!--Begin patron display-->
<div>
<p id="patron-display" class="text-discord-full-white text-left"></p>
</div>
<!--End patron display-->
<br>
<br>
<br>
<br>
<!--Begin dev display-->
<div>
<p id="dev-display" class="text-discord-full-white text-left"></p>
</div>
<!--End dev display-->
<!--Begin dev display-->
<div>
<p id="dev-display" class="text-discord-full-white text-left"></p>
</div>
<!--End dev display-->
<!--Begin shard display-->
<!--End shard display-->
</div>
<!--End data display and edit-->
<!--Begin shard display-->
<!--End shard display-->
</div>
<!--End data display and edit-->
</div>
<!--End container fluid-->
</div>
<!--End container fluid-->
<!--Snackbar for notification popup-->
<div id="snackbar"></div>
</div>
<!-- End of Main Content -->
<!--Snackbar for notification popup-->
<div id="snackbar"></div>
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-discal-blue">
<div class="container my-auto">
<div class="copyright text-center text-discord-full-white my-auto">
<span th:text="'&copy; ' + ${year} + ' DreamExposure Studios'"></span>
<span> | </span>
<a href="/policy/privacy">Privacy</a>
<span> | </span>
<a href="/policy/tos">Terms</a>
<span> | </span>
<a href="/docs/api/overview">API</a>
<span> | </span>
<a href="https://www.dreamexposure.org">DreamExposure</a>
<span> | </span>
<span>DisCal is not endorsed or supported by Discord</span>
</div>
</div>
</footer>
<!-- End of Footer -->
<!-- Footer -->
<footer class="sticky-footer bg-discal-blue">
<div class="container my-auto">
<div class="copyright text-center text-discord-full-white my-auto">
<span th:text="'&copy; ' + ${year} + ' DreamExposure Studios'"></span>
<span> | </span>
<a href="/policy/privacy">Privacy</a>
<span> | </span>
<a href="/policy/tos">Terms</a>
<span> | </span>
<a href="/docs/api/overview">API</a>
<span> | </span>
<a href="https://www.dreamexposure.org">DreamExposure</a>
<span> | </span>
<span>DisCal is not endorsed or supported by Discord</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog"
aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content bg-discal-not-black">
<div class="modal-header">
<h5 class="modal-title text-discal-blue" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span class="text-discal-red" aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p class="text-left text-discord-full-white">
Select "Logout" below if you are ready to end your current session.
</p>
</div>
<div class="modal-footer">
<button class="btn btn-discal-dark-gray text-discord-full-white"
type="button" data-dismiss="modal">Cancel
</button>
aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content bg-discal-not-black">
<div class="modal-header">
<h5 class="modal-title text-discal-blue" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span class="text-discal-red" aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p class="text-left text-discord-full-white">
Select "Logout" below if you are ready to end your current session.
</p>
</div>
<div class="modal-footer">
<button class="btn btn-discal-dark-gray text-discord-full-white"
type="button" data-dismiss="modal">Cancel
</button>
<a class="btn btn-discal-red text-discord-full-white" href="/logout">Logout</a>
</div>
</div>
</div>
<a class="btn btn-discal-red text-discord-full-white" href="/logout">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="/vendor/jquery/jquery.min.js"></script>