refactor dashboard tile building

This commit is contained in:
Simon 2023-11-19 20:27:18 +07:00
parent 02ac590caa
commit 44c4cf93e2
No known key found for this signature in database
GPG Key ID: 2C15AA5E89985DD4
2 changed files with 171 additions and 120 deletions

View File

@ -5,10 +5,13 @@
<h1>Your Archive</h1> <h1>Your Archive</h1>
</div> </div>
<div class="settings-item"> <div class="settings-item">
<h2>Main Overview</h2> <h2>Overview</h2>
<div id="primaryBox" class="info-box info-box-4"> <div id="primaryBox" class="info-box info-box-4">
<p id="loading">Loading...</p> <p id="loading">Loading...</p>
</div> </div>
<div id="secondaryBox" class="info-box info-box-3">
<p id="loading">Loading...</p>
</div>
</div> </div>
<div class="settings-item"> <div class="settings-item">
<h2>Watch Progress</h2> <h2>Watch Progress</h2>

View File

@ -5,158 +5,140 @@
/* globals apiRequest */ /* globals apiRequest */
function primaryStats() { function primaryStats() {
let apiEndpoint = '/api/stats/primary/'; let apiVideoEndpoint = '/api/stats/video/';
let responseData = apiRequest(apiEndpoint, 'GET'); let responseData = apiRequest(apiVideoEndpoint, 'GET');
let primaryBox = document.getElementById('primaryBox');
let primaryBox = document.getElementById('primaryBox');
clearLoading(primaryBox); clearLoading(primaryBox);
let videoTile = buildVideoTile(responseData); let totalTile = buildTotalVideoTile(responseData);
primaryBox.appendChild(videoTile); primaryBox.appendChild(totalTile);
let channelTile = buildChannelTile(responseData); let videosTypeTile = buildVideosTypeTile(responseData);
primaryBox.appendChild(channelTile); primaryBox.appendChild(videosTypeTile);
let playlistTile = buildPlaylistTile(responseData); let shortsTypeTile = buildShortsTypeTile(responseData);
primaryBox.appendChild(playlistTile); primaryBox.appendChild(shortsTypeTile);
let downloadTile = buildDownloadTile(responseData); let streamsTypeTile = buildStreamsTypeTile(responseData);
primaryBox.appendChild(downloadTile); primaryBox.appendChild(streamsTypeTile);
} }
function clearLoading(dashBox) { function secondaryStats() {
dashBox.querySelector('#loading').remove(); let apiChannelEndpoint = '/api/stats/channel/';
let channelResponseData = apiRequest(apiChannelEndpoint, 'GET');
let secondaryBox = document.getElementById('secondaryBox');
clearLoading(secondaryBox);
let channelTile = buildChannelTile(channelResponseData);
secondaryBox.appendChild(channelTile);
let apiPlaylistEndpoint = '/api/stats/playlist/';
let playlistResponseData = apiRequest(apiPlaylistEndpoint, 'GET');
let playlistTile = buildPlaylistTile(playlistResponseData);
secondaryBox.appendChild(playlistTile);
let apiDownloadEndpoint = '/api/stats/download/';
let downloadResponseData = apiRequest(apiDownloadEndpoint, 'GET');
let downloadTile = buildDownloadTile(downloadResponseData);
secondaryBox.appendChild(downloadTile);
} }
function buildTile(titleText) { function buildTotalVideoTile(responseData) {
let tile = document.createElement('div'); const totalCount = responseData.doc_count || 0;
tile.classList.add('info-box-item'); const totalSize = humanFileSize(responseData.media_size || 0);
const content = {
let title = document.createElement('h3'); Items: `${totalCount}`,
'Media Size': `${totalSize}`,
title.innerText = titleText; };
tile.appendChild(title); const tile = buildTile('All: ');
const table = buildTileContenTable(content, 2);
tile.appendChild(table);
return tile; return tile;
} }
function buildTileContenTable(content, rowsWanted) { function buildVideosTypeTile(responseData) {
let contentEntries = Object.entries(content); const videosCount = responseData.type_videos.doc_count || 0;
const videosSize = humanFileSize(responseData.type_videos.media_size || 0);
const nbsp = '\u00A0'; // No-Break Space https://www.compart.com/en/unicode/U+00A0 const content = {
Items: `${videosCount}`,
// Do not add spacing rows when on mobile device 'Media Size': `${videosSize}`,
const isMobile = window.matchMedia('(max-width: 600px)'); };
if (!isMobile.matches) { const tile = buildTile('Regular Videos: ');
if (contentEntries.length < rowsWanted) { const table = buildTileContenTable(content, 2);
const rowsToAdd = rowsWanted - contentEntries.length; tile.appendChild(table);
return tile;
for (let i = 0; i < rowsToAdd; i++) {
contentEntries.push([nbsp, nbsp]);
}
}
}
const table = document.createElement('table');
table.classList.add('agg-channel-table');
const tableBody = document.createElement('tbody');
for (const [key, value] of contentEntries) {
const row = document.createElement('tr');
const leftCell = document.createElement('td');
leftCell.classList.add('agg-channel-name');
// Do not add ":" when its a spacing entry
const keyText = key === nbsp ? key : `${key}: `;
const leftText = document.createTextNode(keyText);
leftCell.appendChild(leftText);
const rightCell = document.createElement('td');
rightCell.classList.add('agg-channel-right-align');
const rightText = document.createTextNode(value);
rightCell.appendChild(rightText);
row.appendChild(leftCell);
row.appendChild(rightCell);
tableBody.appendChild(row);
}
table.appendChild(tableBody);
return table;
} }
function buildVideoTile(responseData) { function buildShortsTypeTile(responseData) {
let tile = buildTile(`Video types: `); const shortsCount = responseData.type_shorts.doc_count || 0;
const shortsSize = humanFileSize(responseData.type_shorts.media_size || 0);
const total = responseData.videos.total || 0;
const videos = responseData.videos.videos || 0;
const shorts = responseData.videos.shorts || 0;
const streams = responseData.videos.streams || 0;
const content = { const content = {
Videos: `${videos}/${total}`, Items: `${shortsCount}`,
Shorts: `${shorts}/${total}`, 'Media Size': `${shortsSize}`,
Streams: `${streams}/${total}`,
}; };
const tile = buildTile('Shorts: ');
const table = buildTileContenTable(content, 3); const table = buildTileContenTable(content, 2);
tile.appendChild(table); tile.appendChild(table);
return tile;
}
function buildStreamsTypeTile(responseData) {
const streamsCount = responseData.type_streams.doc_count || 0;
const streamsSize = humanFileSize(responseData.type_streams.media_size || 0);
const content = {
Items: `${streamsCount}`,
'Media Size': `${streamsSize}`,
};
const tile = buildTile('Streams: ');
const table = buildTileContenTable(content, 2);
tile.appendChild(table);
return tile; return tile;
} }
function buildChannelTile(responseData) { function buildChannelTile(responseData) {
let tile = buildTile(`Channels: `); let tile = buildTile('Channels: ');
const total = responseData.doc_count || 0;
const total = responseData.channels.total || 0; const subscribed = responseData.subscribed_true || 0;
const subscribed = responseData.channels.sub_true || 0; const active = responseData.active_true || 0;
const content = { const content = {
Subscribed: `${subscribed}/${total}`, Subscribed: subscribed,
Active: active,
Total: total,
}; };
const table = buildTileContenTable(content, 3); const table = buildTileContenTable(content, 3);
tile.appendChild(table); tile.appendChild(table);
return tile; return tile;
} }
function buildPlaylistTile(responseData) { function buildPlaylistTile(responseData) {
let tile = buildTile(`Playlists:`); let tile = buildTile('Playlists: ');
const total = responseData.doc_count || 0;
const total = responseData.playlists.total || 0; const subscribed = responseData.subscribed_true || 0;
const subscribed = responseData.playlists.sub_true || 0; const active = responseData.active_true || 0;
const content = { const content = {
Subscribed: `${subscribed}/${total}`, Subscribed: subscribed,
Active: active,
Total: total,
}; };
const table = buildTileContenTable(content, 2);
const table = buildTileContenTable(content, 3);
tile.appendChild(table); tile.appendChild(table);
return tile; return tile;
} }
function buildDownloadTile(responseData) { function buildDownloadTile(responseData) {
let tile = buildTile('Downloads'); const pendingTotal = responseData.pending || 0;
let tile = buildTile(`Downloads Pending: ${pendingTotal}`);
const pending = responseData.downloads.pending || 0; const pendingVideos = responseData.pending_videos || 0;
const ignored = responseData.downloads.ignore || 0; const pendingShorts = responseData.pending_shorts || 0;
const pendingStreams = responseData.pending_streams || 0;
const content = { const content = {
Pending: pending, Videos: pendingVideos,
Ignored: ignored, Shorts: pendingShorts,
Streams: pendingStreams,
}; };
const table = buildTileContenTable(content, 3); const table = buildTileContenTable(content, 3);
tile.appendChild(table); tile.appendChild(table);
return tile; return tile;
@ -180,11 +162,6 @@ function watchStats() {
watchBox.appendChild(thirdCard); watchBox.appendChild(thirdCard);
} }
function capitalizeFirstLetter(string) {
// source: https://stackoverflow.com/a/1026087
return string.charAt(0).toUpperCase() + string.slice(1);
}
function buildWatchTile(title, watchDetail) { function buildWatchTile(title, watchDetail) {
const items = watchDetail?.items ?? 0; const items = watchDetail?.items ?? 0;
const duration = watchDetail?.duration ?? 0; const duration = watchDetail?.duration ?? 0;
@ -248,11 +225,6 @@ function buildDailyStat(dailyStat) {
return tile; return tile;
} }
function humanFileSize(size) {
let i = size === 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));
return (size / Math.pow(1024, i)).toFixed(1) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
}
function buildChannelRow(id, name, value) { function buildChannelRow(id, name, value) {
let tableRow = document.createElement('tr'); let tableRow = document.createElement('tr');
@ -309,6 +281,81 @@ function addBiggestChannelByMediaSize() {
} }
} }
function clearLoading(dashBox) {
dashBox.querySelector('#loading').remove();
}
function capitalizeFirstLetter(string) {
// source: https://stackoverflow.com/a/1026087
return string.charAt(0).toUpperCase() + string.slice(1);
}
function humanFileSize(size) {
let i = size === 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));
return (size / Math.pow(1024, i)).toFixed(1) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
}
function buildTile(titleText) {
let tile = document.createElement('div');
tile.classList.add('info-box-item');
let title = document.createElement('h3');
title.innerText = titleText;
tile.appendChild(title);
return tile;
}
function buildTileContenTable(content, rowsWanted) {
let contentEntries = Object.entries(content);
const nbsp = '\u00A0'; // No-Break Space https://www.compart.com/en/unicode/U+00A0
// Do not add spacing rows when on mobile device
const isMobile = window.matchMedia('(max-width: 600px)');
if (!isMobile.matches) {
if (contentEntries.length < rowsWanted) {
const rowsToAdd = rowsWanted - contentEntries.length;
for (let i = 0; i < rowsToAdd; i++) {
contentEntries.push([nbsp, nbsp]);
}
}
}
const table = document.createElement('table');
table.classList.add('agg-channel-table');
const tableBody = document.createElement('tbody');
for (const [key, value] of contentEntries) {
const row = document.createElement('tr');
const leftCell = document.createElement('td');
leftCell.classList.add('agg-channel-name');
// Do not add ":" when its a spacing entry
const keyText = key === nbsp ? key : `${key}: `;
const leftText = document.createTextNode(keyText);
leftCell.appendChild(leftText);
const rightCell = document.createElement('td');
rightCell.classList.add('agg-channel-right-align');
const rightText = document.createTextNode(value);
rightCell.appendChild(rightText);
row.appendChild(leftCell);
row.appendChild(rightCell);
tableBody.appendChild(row);
}
table.appendChild(tableBody);
return table;
}
function biggestChannel() { function biggestChannel() {
addBiggestChannelByDocCount(); addBiggestChannelByDocCount();
addBiggestChannelByDuration(); addBiggestChannelByDuration();
@ -317,6 +364,7 @@ function biggestChannel() {
async function buildStats() { async function buildStats() {
primaryStats(); primaryStats();
secondaryStats();
watchStats(); watchStats();
downloadHist(); downloadHist();
biggestChannel(); biggestChannel();