mirror of
https://github.com/chylex/Discord-History-Tracker.git
synced 2025-04-15 16:10:32 +03:00
Refactor user filter PR to make adding filters easier & cleanup UI
This commit is contained in:
parent
fa52c3aeb0
commit
35183fd270
@ -31,12 +31,6 @@
|
||||
<option value="0">All messages </option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div> <!-- needed to stop the select from messing up -->
|
||||
<select id="opt-messages-by-user">
|
||||
<option value="">Filter messages by user </option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="nav">
|
||||
<button id="nav-first" data-nav="first">«</button>
|
||||
@ -46,6 +40,21 @@
|
||||
<button id="nav-last" data-nav="last">»</button>
|
||||
</div>
|
||||
|
||||
<div class="splitter"></div>
|
||||
|
||||
<div> <!-- needed to stop the select from messing up -->
|
||||
<select id="opt-messages-filter">
|
||||
<option value="">No filter </option>
|
||||
<option value="user">Filter messages by user </option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div id="opt-filter-list">
|
||||
<select id="opt-filter-user" data-filter-type="user">
|
||||
<option value="">Select user...</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<button id="btn-about">About</button>
|
||||
|
@ -26,14 +26,18 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
|
||||
STATE.setMessagesPerPage(GUI.getOptionMessagesPerPage());
|
||||
|
||||
GUI.onOptionMessagesByUserChanged(() => {
|
||||
STATE.setMessagesByUser(GUI.getOptionMessagesByUser());
|
||||
GUI.onOptMessageFilterChanged(filter => {
|
||||
STATE.setActiveFilter(filter);
|
||||
});
|
||||
|
||||
|
||||
GUI.onNavigationButtonClicked(action => {
|
||||
STATE.updateCurrentPage(action);
|
||||
});
|
||||
|
||||
STATE.onUsersRefreshed(users => {
|
||||
GUI.updateUserList(users);
|
||||
});
|
||||
|
||||
STATE.onChannelsRefreshed(channels => {
|
||||
GUI.updateChannelList(channels, STATE.selectChannel);
|
||||
});
|
||||
@ -43,8 +47,4 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
GUI.updateMessageList(messages);
|
||||
GUI.scrollMessagesToTop();
|
||||
});
|
||||
|
||||
STATE.onUsersRefreshed(users => {
|
||||
GUI.updateUserFilter(users);
|
||||
});
|
||||
});
|
||||
|
@ -1,9 +1,22 @@
|
||||
var GUI = (function(){
|
||||
var eventOnFileUploaded;
|
||||
var eventOnOptMessagesPerPageChanged;
|
||||
var eventOnOptMessagesByUserChanged;
|
||||
var eventOnOptMessageFilterChanged;
|
||||
var eventOnNavButtonClicked;
|
||||
|
||||
var getActiveFilter = function(){
|
||||
var active = DOM.fcls("active", DOM.id("opt-filter-list"));
|
||||
|
||||
return active && active.value !== "" ? {
|
||||
"type": active.getAttribute("data-filter-type"),
|
||||
"value": active.value
|
||||
} : null;
|
||||
};
|
||||
|
||||
var triggerFilterChanged = function(){
|
||||
eventOnOptMessageFilterChanged && eventOnOptMessageFilterChanged(getActiveFilter());
|
||||
};
|
||||
|
||||
var showModal = function(width, html){
|
||||
var dialog = DOM.id("dialog");
|
||||
dialog.innerHTML = html;
|
||||
@ -59,6 +72,8 @@ var GUI = (function(){
|
||||
*/
|
||||
setup: function(){
|
||||
var inputUploadedFile = DOM.id("uploaded-file");
|
||||
var inputMessageFilter = DOM.id("opt-messages-filter");
|
||||
var containerFilterList = DOM.id("opt-filter-list");
|
||||
|
||||
DOM.id("btn-upload-file").addEventListener("click", () => {
|
||||
inputUploadedFile.click();
|
||||
@ -67,16 +82,31 @@ var GUI = (function(){
|
||||
inputUploadedFile.addEventListener("change", () => {
|
||||
if (eventOnFileUploaded && eventOnFileUploaded(inputUploadedFile.files)){
|
||||
inputUploadedFile.value = null;
|
||||
|
||||
inputMessageFilter.value = "";
|
||||
inputMessageFilter.dispatchEvent(new Event("change"));
|
||||
}
|
||||
});
|
||||
|
||||
inputMessageFilter.value = ""; // required to prevent browsers from remembering old value
|
||||
|
||||
inputMessageFilter.addEventListener("change", () => {
|
||||
DOM.cls("active", containerFilterList).forEach(ele => ele.classList.remove("active"));
|
||||
|
||||
if (inputMessageFilter.value){
|
||||
containerFilterList.querySelector("[data-filter-type='"+inputMessageFilter.value+"']").classList.add("active");
|
||||
}
|
||||
|
||||
triggerFilterChanged();
|
||||
});
|
||||
|
||||
Array.prototype.forEach.call(containerFilterList.children, ele => {
|
||||
ele.addEventListener("change", e => triggerFilterChanged());
|
||||
});
|
||||
|
||||
DOM.id("opt-messages-per-page").addEventListener("change", () => {
|
||||
eventOnOptMessagesPerPageChanged && eventOnOptMessagesPerPageChanged();
|
||||
});
|
||||
|
||||
DOM.id("opt-messages-by-user").addEventListener("change", () => {
|
||||
eventOnOptMessagesByUserChanged && eventOnOptMessagesByUserChanged();
|
||||
});
|
||||
|
||||
DOM.tag("button", DOM.fcls("nav")).forEach(button => {
|
||||
button.disabled = true;
|
||||
@ -119,10 +149,10 @@ var GUI = (function(){
|
||||
},
|
||||
|
||||
/*
|
||||
* Sets a callback for when the user changes the messages by user option. The callback is not passed any arguments.
|
||||
* Sets a callback for when the user changes the active filter. The callback is passed either null or an object such as { type: <filter type>, value: <filter value> }.
|
||||
*/
|
||||
onOptionMessagesByUserChanged: function(callback){
|
||||
eventOnOptMessagesByUserChanged = callback;
|
||||
onOptMessageFilterChanged: function(callback){
|
||||
eventOnOptMessageFilterChanged = callback;
|
||||
},
|
||||
|
||||
/*
|
||||
@ -142,13 +172,6 @@ var GUI = (function(){
|
||||
getOptionMessagesPerPage: function(){
|
||||
return parseInt(DOM.id("opt-messages-per-page").value, 10);
|
||||
},
|
||||
|
||||
/*
|
||||
* Returns the user which to filter messages by.
|
||||
*/
|
||||
getOptionMessagesByUser: function(){
|
||||
return DOM.id("opt-messages-by-user").value;
|
||||
},
|
||||
|
||||
/*
|
||||
* Updates the navigation text and buttons.
|
||||
@ -163,9 +186,9 @@ var GUI = (function(){
|
||||
DOM.id("nav-last").disabled = currentPage === (totalPages || 1);
|
||||
},
|
||||
|
||||
// ------------
|
||||
// Channel list
|
||||
// ------------
|
||||
// --------------
|
||||
// Updating lists
|
||||
// --------------
|
||||
|
||||
/*
|
||||
* Updates the channel list and sets up their click events. The callback is triggered whenever a channel is selected, and takes the channel ID as its argument.
|
||||
@ -177,7 +200,11 @@ var GUI = (function(){
|
||||
eleChannels.innerHTML = "";
|
||||
}
|
||||
else{
|
||||
eleChannels.innerHTML = channels.filter(channel => channel.msgcount > 0).map(channel => DISCORD.getChannelHTML(channel)).join("");
|
||||
if (getActiveFilter() != null){
|
||||
channels = channels.filter(channel => channel.msgcount > 0);
|
||||
}
|
||||
|
||||
eleChannels.innerHTML = channels.map(channel => DISCORD.getChannelHTML(channel)).join("");
|
||||
|
||||
Array.prototype.forEach.call(eleChannels.children, ele => {
|
||||
ele.addEventListener("click", e => {
|
||||
@ -206,31 +233,26 @@ var GUI = (function(){
|
||||
},
|
||||
|
||||
/*
|
||||
* Updates the select box with all possibly user names.
|
||||
* Updates the user filter list.
|
||||
*/
|
||||
updateUserFilter: function(users){
|
||||
var select = DOM.id("opt-messages-by-user");
|
||||
|
||||
// Remove all but first option
|
||||
for (var i = select.length; i > 0; i--) {
|
||||
select.remove(i);
|
||||
updateUserList: function(users){
|
||||
var eleSelect = DOM.id("opt-filter-user");
|
||||
|
||||
while(eleSelect.length > 1){
|
||||
eleSelect.remove(1);
|
||||
}
|
||||
|
||||
|
||||
var options = [];
|
||||
for (var key in users) {
|
||||
// Skip loop if the property is from prototype
|
||||
if (!users.hasOwnProperty(key)) continue;
|
||||
|
||||
|
||||
for(var key of Object.keys(users)){
|
||||
var option = document.createElement("option");
|
||||
option.value = key;
|
||||
option.text = users[key].name;
|
||||
options.push(option);
|
||||
}
|
||||
options.sort((a, b) => {
|
||||
return a.text.toLowerCase().localeCompare(b.text.toLowerCase());
|
||||
}).forEach(option => {
|
||||
select.add(option);
|
||||
});
|
||||
|
||||
options.sort((a, b) => a.text.toLocaleLowerCase().localeCompare(b.text.toLocaleLowerCase()));
|
||||
options.forEach(option => eleSelect.add(option));
|
||||
},
|
||||
|
||||
/*
|
||||
|
@ -26,6 +26,10 @@ SAVEFILE.prototype.getChannelById = function(channel){
|
||||
return this.meta.channels[channel] || { "id": channel, "name": channel };
|
||||
};
|
||||
|
||||
SAVEFILE.prototype.getUsers = function(){
|
||||
return this.meta.users;
|
||||
};
|
||||
|
||||
SAVEFILE.prototype.getUser = function(index){
|
||||
return this.meta.users[this.meta.userindex[index]] || { "name": "<unknown>" };
|
||||
};
|
||||
@ -34,20 +38,6 @@ SAVEFILE.prototype.getUserById = function(user){
|
||||
return this.meta.users[user] || { "name": user };
|
||||
};
|
||||
|
||||
SAVEFILE.prototype.getMessageCount = function(channel){
|
||||
return Object.keys(this.getMessages(channel)).length;
|
||||
};
|
||||
|
||||
SAVEFILE.prototype.getFilteredMessageCount = function(channel, userindex){
|
||||
if (userindex === -1) return this.getMessageCount(channel);
|
||||
|
||||
var count = 0;
|
||||
UTILS.forEachValue(this.getMessages(channel), messageObject => {
|
||||
if (messageObject.u === userindex) count++;
|
||||
});
|
||||
return count;
|
||||
};
|
||||
|
||||
SAVEFILE.prototype.getAllMessages = function(){
|
||||
var messages = {};
|
||||
|
||||
@ -56,6 +46,8 @@ SAVEFILE.prototype.getAllMessages = function(){
|
||||
});
|
||||
|
||||
return messages;
|
||||
SAVEFILE.prototype.getUserIndex = function(user){
|
||||
return this.meta.userindex.indexOf(user);
|
||||
};
|
||||
|
||||
SAVEFILE.prototype.getMessages = function(channel){
|
||||
|
@ -11,7 +11,7 @@ var STATE = (function(){
|
||||
var selectedChannel;
|
||||
var currentPage;
|
||||
var messagesPerPage;
|
||||
var messagesByUser;
|
||||
var filterFunction;
|
||||
|
||||
// ----------------------------------
|
||||
// Channel and message refresh events
|
||||
@ -53,10 +53,10 @@ var STATE = (function(){
|
||||
FILE = file;
|
||||
MSGS = null;
|
||||
currentPage = 1;
|
||||
|
||||
|
||||
triggerUsersRefreshed();
|
||||
triggerChannelsRefreshed();
|
||||
triggerMessagesRefreshed();
|
||||
triggerUsersRefreshed();
|
||||
};
|
||||
|
||||
ROOT.getChannelName = function(channel){
|
||||
@ -74,24 +74,34 @@ var STATE = (function(){
|
||||
// --------------------------
|
||||
// Channel list and selection
|
||||
// --------------------------
|
||||
|
||||
var getFilteredMessageKeys = function(channel){
|
||||
var messages = FILE.getMessages(channel);
|
||||
var keys = Object.keys(messages);
|
||||
|
||||
if (filterFunction){
|
||||
keys = keys.filter(key => filterFunction(messages[key]));
|
||||
}
|
||||
|
||||
return keys;
|
||||
};
|
||||
|
||||
ROOT.getChannelList = function(){
|
||||
var channels = FILE.getChannels();
|
||||
var userindex = messagesByUser ? FILE.meta.userindex.indexOf(messagesByUser) : -1;
|
||||
|
||||
return Object.keys(channels).map(key => ({
|
||||
"id": key,
|
||||
"name": channels[key].name,
|
||||
"server": FILE.getServer(channels[key].server),
|
||||
"msgcount": FILE.getFilteredMessageCount(key, userindex)
|
||||
"msgcount": getFilteredMessageKeys(key).length
|
||||
}));
|
||||
};
|
||||
|
||||
ROOT.selectChannel = function(channel){
|
||||
currentPage = 1;
|
||||
selectedChannel = channel;
|
||||
MSGS = Object.keys(FILE.getMessages(channel)).sort(PROCESSOR.SORTER.oldestToNewest);
|
||||
|
||||
|
||||
MSGS = getFilteredMessageKeys(channel).sort(PROCESSOR.SORTER.oldestToNewest);
|
||||
triggerMessagesRefreshed();
|
||||
};
|
||||
|
||||
@ -102,19 +112,6 @@ var STATE = (function(){
|
||||
// ------------
|
||||
// Message list
|
||||
// ------------
|
||||
ROOT.getFilteredMessageList = function(){
|
||||
if (!messagesByUser) {
|
||||
return MSGS;
|
||||
}
|
||||
|
||||
var pos = FILE.meta.userindex.indexOf(messagesByUser);
|
||||
var messages = FILE.getMessages(selectedChannel);
|
||||
return MSGS.filter(key => {
|
||||
var message = messages[key];
|
||||
return message.u == pos;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
ROOT.getMessageList = function(){
|
||||
if (!MSGS){
|
||||
@ -124,7 +121,7 @@ var STATE = (function(){
|
||||
var messages = FILE.getMessages(selectedChannel);
|
||||
var startIndex = messagesPerPage*(ROOT.getCurrentPage()-1);
|
||||
|
||||
return ROOT.getFilteredMessageList().slice(startIndex, !messagesPerPage ? undefined : startIndex+messagesPerPage).map(key => {
|
||||
return MSGS.slice(startIndex, !messagesPerPage ? undefined : startIndex+messagesPerPage).map(key => {
|
||||
var message = messages[key];
|
||||
|
||||
return {
|
||||
@ -137,24 +134,32 @@ var STATE = (function(){
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
ROOT.getUserList = function(){
|
||||
if (!FILE){
|
||||
return [];
|
||||
}
|
||||
|
||||
return FILE.meta.users;
|
||||
};
|
||||
|
||||
// ----------
|
||||
// Filtering
|
||||
// ----------
|
||||
|
||||
ROOT.setActiveFilter = function(filter){
|
||||
switch(filter ? filter.type : ""){
|
||||
case "user":
|
||||
filterFunction = PROCESSOR.FILTER.byUser(FILE.getUserIndex(filter.value));
|
||||
break;
|
||||
|
||||
ROOT.setMessagesByUser = function(key){
|
||||
currentPage = 1;
|
||||
messagesByUser = key;
|
||||
default:
|
||||
filterFunction = null;
|
||||
break;
|
||||
}
|
||||
|
||||
triggerChannelsRefreshed();
|
||||
triggerMessagesRefreshed();
|
||||
ROOT.selectChannel(selectedChannel); // resets current page and updates messages
|
||||
};
|
||||
|
||||
// -----
|
||||
// Users
|
||||
// -----
|
||||
|
||||
ROOT.getUserList = function(){
|
||||
return FILE ? FILE.getUsers() : [];
|
||||
};
|
||||
|
||||
// ----------
|
||||
@ -188,7 +193,7 @@ var STATE = (function(){
|
||||
};
|
||||
|
||||
ROOT.getPageCount = function(){
|
||||
return !MSGS ? 0 : (!messagesPerPage ? 1 : Math.ceil(ROOT.getFilteredMessageList().length/messagesPerPage));
|
||||
return !MSGS ? 0 : (!messagesPerPage ? 1 : Math.ceil(MSGS.length/messagesPerPage));
|
||||
};
|
||||
|
||||
// --------
|
||||
|
@ -60,3 +60,11 @@
|
||||
#menu .nav > button, #menu .nav > p {
|
||||
margin: 8px 1px;
|
||||
}
|
||||
|
||||
#opt-filter-list > select, #opt-filter-list > input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#opt-filter-list > .active {
|
||||
display: block;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user