2020-07-14 18:56:20 +00:00
< html >
<!doctype html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1, shrink-to-fit=no" >
2020-07-16 10:34:29 +00:00
< meta name = "description" content = "Twitch Sings tools for data analysis" >
2020-07-14 18:56:20 +00:00
< meta name = "author" content = "Martyn Ranyard" >
2020-07-16 10:34:29 +00:00
< title > Twitch Sings Tools< / title >
2020-07-14 18:56:20 +00:00
<!-- Bootstrap core CSS -->
< link href = "https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel = "stylesheet" crossorigin = "anonymous" >
<!-- Custom styles for this template -->
< link href = "/cover.css" rel = "stylesheet" >
< style >
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
2020-07-16 10:34:29 +00:00
#insightspanel > table:nth-child(1) > thead:nth-child(1) > tr:nth-child(1) > td:nth-child(1)
2020-07-14 18:56:20 +00:00
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
li.match-nomatch{
background-color: #1e2122;
}
li.match-matchtrack{
background-color: #E9B000;
}
li.match-fullmatch{
background-color: #008F95;
}
li.match-matchtrackfuzzt{
background-color: darkgray;
}
li.match-fullmatchfuzzy{
background-color: darkgray;
}
a{
text-decoration-line: underline;
}
.displaySetting{
display: inline
}
.hiddenDisplaySetting{
display: none;
}
.hiddenSave {
display: none;
}
.editSetting{
display: none;
}
.visibleEditSetting{
display: inline;
}
.visibleSave {
display: inline;
}
2020-07-15 19:19:06 +00:00
th {
font-weight: bold;
font-style: italic;
}
2020-07-16 16:01:04 +00:00
#csvpanel td {
padding: 5px;
}
#csvpanel th {
padding: 5px;
}
2020-07-14 18:56:20 +00:00
< / style >
< / head >
< body class = "text-center" >
< div class = "cover-container d-flex w-100 h-100 p-3 mx-auto flex-column" >
< header class = "masthead mb-auto" >
< div class = "inner" >
2020-07-16 10:34:29 +00:00
< h3 class = "masthead-brand" > Twitch Sings Tools< / h3 >
2020-07-14 18:56:20 +00:00
< nav class = "nav nav-masthead justify-content-center" >
< a class = "nav-link active" href = "/" > Home< / a >
< / nav >
< / div >
< / header >
< main role = "main" class = "inner cover" >
< script >
function editMode() {
var alldisps = document.getElementsByClassName("displaySetting");
for (item of alldisps) {
item.classList.add("hiddenDisplaySetting")
}
for (item of alldisps) {
item.classList.remove("displaySetting")
}
var alldisps = document.getElementsByClassName("editSetting");
for (item of alldisps) {
item.classList.add("visibleEditSetting")
}
for (item of alldisps) {
item.classList.remove("editSetting")
}
document.getElementById("saveButton").classList.remove("hiddenSave")
document.getElementById("saveButton").classList.add("visibleSave")
document.getElementById("leaveButton").classList.remove("hiddenSave")
document.getElementById("leaveButton").classList.add("visibleSave")
document.getElementById("yuhateme").classList.remove("hiddenSave")
document.getElementById("yuhateme").classList.add("visibleSave")
}
< / script >
2020-07-16 10:34:29 +00:00
< h1 class = "cover-heading" > Twitch Sings Tools admin panel for {{.Channel}}!!!< / h1 >
< ul class = "nav nav-tabs" style = "width: 100%;" >
2020-07-15 19:19:06 +00:00
< li class = "nav-item" >
< a id = "insights" class = "nav-link active panel" href = "#" onclick = "tabClick(this)" > Insights< / a >
< / li >
< li class = "nav-item" >
< a id = "data" class = "nav-link panel" href = "#" onclick = "tabClick(this)" > Data< / a >
< / li >
< li class = "nav-item" >
< a id = "csv" class = "nav-link panel" href = "#" onclick = "tabClick(this)" > CSV< / a >
< / li >
< li class = "nav-item" >
< a id = "bot" class = "nav-link panel" href = "#" onclick = "tabClick(this)" > Bot< / a >
< / li >
< / ul >
2020-07-16 10:34:29 +00:00
< div style = "width: 100%; overflow-y: scroll; display: block;" id = "insightspanel" class = "controlpanel" >
2020-07-15 19:19:06 +00:00
< table >
2020-07-16 10:34:29 +00:00
< tr > < th > < h2 > Top 10 Songs : < / h2 > < / th > < th > < h2 > Top 10 Singers : < / h2 > < / th > < / tr >
< tr > < td > < table >
< thead > < tr > < th > Song< / th > < th > Sings< / th > < / tr > < / thead >
{{ range .TopNSongs }}
< tr > < td > {{ .SongTitle }}< / td > < td > {{ .Sings }}< / td > < / tr >
{{ end }}
< / table > < / td > < td > < table >
< thead > < tr > < th > Singer< / th > < th > Sings< / th > < / tr > < / thead >
{{ range .TopNSingers }}
< tr > < td > {{ .SingerName }}< / td > < td > {{ .Sings }}< / td > < / tr >
{{ end }}
< / table > < / td > < / tr >
< / table >
2020-07-15 19:19:06 +00:00
< / div >
2020-07-16 10:34:29 +00:00
< div style = "width: 100%; overflow-y: scroll; display: none;" id = "datapanel" class = "controlpanel" >
2020-07-31 12:59:48 +00:00
< table id = "dataTable" >
2020-07-16 20:00:49 +00:00
< thead > < tr > < th > Published< / th > < th > What< / th > < th > Who< / th > < th > Last sang this song< / th > < th > Last dueted with performer< / th > < / th > < / thead >
2020-07-15 19:19:06 +00:00
{{ range .SongData }}
2020-07-16 10:34:29 +00:00
< tr > < td title = "{{ .Date }}" > {{ .NiceDate }}< / td > < td > {{ .SongTitle }}< / td > < td > {{ .OtherSinger }}< / td > < td title = "{{ .LastSungSong }}" > {{ .NiceLastSungSong }}< / td > < td title = "{{ .LastSungSinger }}" > {{ .NiceLastSungSinger }}< / td > < / tr >
2020-07-15 19:19:06 +00:00
{{ end }}
< / table >
< / div >
2020-07-16 10:34:29 +00:00
< div style = "width: 100%; overflow-y: scroll; display: none;" id = "csvpanel" class = "controlpanel" >
2020-07-16 16:01:04 +00:00
< h3 > Download your data as :< / h3 >
< center >
< table border = "2" >
< tr > < th > CSV< / th > < th > TSV< / th > < / tr >
< tr > < td > < a href = "/csv/{{.Channel}}/{{.ChannelKey}}" > here< / a > < / td > < td > < a href = "/tsv/{{.Channel}}/{{.ChannelKey}}" > here< / a > < / td > < / tr >
< / table >
< / center >
< h3 > Excel is not very good at handling CSV format it seems...< / h3 >
< p > It is important to "Import Data" not "Open" the csv in many cases (8 year old discussion of this behaviour here) - from that post the instructions are : < / p >
< blockquote > In Excel, DATA tab, in the Get External Data subsection, click "From Text" and import your CSV in the Wizard.< / blockquote >
2020-07-16 20:00:49 +00:00
< p > LibreOffice calc kinda just works...just sayin' ;-)< / p >
2020-07-15 19:19:06 +00:00
< / div >
2020-07-16 10:34:29 +00:00
< div style = "width: 100%; overflow-y: scroll; display: none;" id = "botpanel" class = "controlpanel" >
< h2 > The bot isn't really ready yet... it just has the old Karaokards facility at the moment. I woudn't bother inviting it yet.< / h2 >
2020-07-14 18:56:20 +00:00
{{ if .HasLeft }}
< h2 > Not in your channel at the moment!< / h2 >
< p > The bot is not currently in your channel, chances are you've not ever asked it to join, you asked it to leave, or something went horribly wrong.< / p >
< p > You can invite the bot to your channel by clicking here : < input id = "joinButton" type = "submit" name = "join" value = "Come on in" > < / p >
{{ else }}
2020-07-15 19:19:06 +00:00
< form method = "POST" >
2020-07-14 18:56:20 +00:00
{{ if .Leaving }}
< h2 > Do you really want this bot to leave your channel?< / h2 >
< p > < input id = "leaveButton" type = "submit" name = "reallyleave" value = "Really leave twitch channel" > < / p >
{{ else }}
< h2 > Note you can give your moderators the url you are on right now to control this bot. They don't have to be logged into twitch to do so.< / h2 >
< table >
2020-07-16 10:34:29 +00:00
< thead > < tr > < th > Channel Data :< / th > < th > < input type = "button" value = "Edit" onclick = "javascript:editMode();" > < / th > < / tr > < / thead >
2020-07-14 18:56:20 +00:00
< tbody >
< tr > < td > Member of channel since {{.SinceTimeUTC}}< / td > < / tr >
< tr > < td > Command for prompt:< / td > < td class = "displaySetting" > < / tdclass > {{.Command}}< / td > < td class = "editSetting" > < input type = "text" name = "Command" value = "{{.Command}}" > < / td > < / tr >
< tr > < td > Extra prompts (one per line):< / td > < td class = "displaySetting" > {{.ExtraStrings}}< / td > < td class = "editSetting" > < textarea name = "ExtraStrings" > {{.ExtraStrings}}< / textarea > < / td > < / tr >
< tr > < td > < / td > < td > < input id = "saveButton" type = "submit" class = "hiddenSave" name = "save" value = "Save changes" > < / td > < / tr >
< tr id = "yuhateme" class = "hiddenSave" > < td > Or... please don't go but...< / td > < / tr >
< tr > < td > < input id = "leaveButton" type = "submit" class = "hiddenSave" name = "leave" value = "Leave twitch channel" > < / td > < / tr >
< / tbody >
< / table >
{{ end }}
{{ end }}
2020-07-15 19:19:06 +00:00
< / div >
2020-07-14 18:56:20 +00:00
< / form >
2020-07-15 19:19:06 +00:00
< script type = "text/javascript" >
function tabClick(self) {
var theTabs = document.querySelectorAll(".panel")
for (tab of theTabs) {
tab.className = "nav-link panel"
}
self.className = "nav-link panel active"
var thePanels = document.querySelectorAll(".controlpanel")
for (panel of thePanels) {
panel.style.display = "none"
}
document.getElementById(self.id+"panel").style.display = "block"
}
2020-07-31 12:59:48 +00:00
/**
* Modified and more readable version of the answer by Paul S. to sort a table with ASC and DESC order
* with the < thead > and < tbody > structure easily.
*
* https://stackoverflow.com/a/14268260/4241030
*/
var TableSorter = {
makeSortable: function(table){
// Store context of this in the object
var _this = this;
var th = table.tHead, i;
th & & (th = th.rows[0]) & & (th = th.cells);
if (th){
i = th.length;
}else{
return; // if no `< thead > ` then do nothing
}
// Loop through every < th > inside the header
while (--i >= 0) (function (i) {
var dir = 1;
// Append click listener to sort
th[i].addEventListener('click', function () {
_this._sort(table, i, (dir = 1 - dir));
});
}(i));
},
_sort: function (table, col, reverse) {
var tb = table.tBodies[0], // use `< tbody > ` to ignore `< thead > ` and `< tfoot > ` rows
tr = Array.prototype.slice.call(tb.rows, 0), // put rows into array
i;
reverse = -((+reverse) || -1);
// Sort rows
tr = tr.sort(function (a, b) {
// `-1 *` if want opposite order
return reverse * (
// Using `.textContent.trim()` for test
a.cells[col].textContent.trim().localeCompare(
b.cells[col].textContent.trim()
)
);
});
for(i = 0; i < tr.length ; + + i ) {
// Append rows in new order
tb.appendChild(tr[i]);
}
}
};
window.onload = function(){
TableSorter.makeSortable(document.getElementById("dataTable"));
};
2020-07-15 19:19:06 +00:00
< / script >
2020-07-14 18:56:20 +00:00
< / main >
2020-07-15 19:19:06 +00:00
< footer class = "mastfoot mt-auto" >
2020-07-14 18:56:20 +00:00
< div class = "inner" >
< p > Cover template for < a href = "https://getbootstrap.com/" > Bootstrap< / a > , by < a href = "https://twitter.com/mdo" > @mdo< / a > .< / p >
< / div >
< / footer >
< / div >
< / body >
< / html >
< / body >
2020-07-15 19:19:06 +00:00
< / html >