From 14cbda4878f21b9691ca83ac8d0e6ab84313f17a Mon Sep 17 00:00:00 2001 From: sphericle <86196223+sphericle@users.noreply.github.com> Date: Fri, 4 Apr 2025 22:03:23 -0400 Subject: [PATCH 01/12] parse uri on frontend --- .../static/js/statsviewer/individual.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js index d27a02b9..831e5cc1 100644 --- a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js +++ b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js @@ -161,7 +161,14 @@ $(window).on("load", function () { document.getElementById("statsviewer") ); - window.statsViewer.initialize(); + window.statsViewer.initialize().then(() => { + let url = window.location.href; + let params = new URLSearchParams(url.split('?')[1]); + let playerId = params.get('player'); + if (playerId) { + window.statsViewer.selectArbitrary(playerId) + } + }); new Dropdown(document.getElementById("continent-dropdown")).addEventListener( (selected) => { From baa48548c3dad9acd3048110dee0a879fc94eba6 Mon Sep 17 00:00:00 2001 From: sphericle <86196223+sphericle@users.noreply.github.com> Date: Wed, 9 Apr 2025 18:51:44 -0400 Subject: [PATCH 02/12] click to copy sv link --- pointercrate-core-pages/static/css/ui.css | 4 ++++ pointercrate-demonlist-pages/static/css/statsviewer.css | 6 +++++- .../static/js/modules/statsviewer.js | 2 ++ .../static/js/statsviewer/individual.js | 6 ++++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/pointercrate-core-pages/static/css/ui.css b/pointercrate-core-pages/static/css/ui.css index 64524fd1..950512fd 100644 --- a/pointercrate-core-pages/static/css/ui.css +++ b/pointercrate-core-pages/static/css/ui.css @@ -702,3 +702,7 @@ ul.selection-list li { .tab-active { color: #0881c6; } + +#claims-claim-panel > a.button { + width: fit-content; +} diff --git a/pointercrate-demonlist-pages/static/css/statsviewer.css b/pointercrate-demonlist-pages/static/css/statsviewer.css index 755477c1..05871192 100644 --- a/pointercrate-demonlist-pages/static/css/statsviewer.css +++ b/pointercrate-demonlist-pages/static/css/statsviewer.css @@ -49,7 +49,11 @@ flex-grow: 2; } +.name-main-span:hover { + cursor: pointer; + text-decoration: underline; +} .tooltip:hover .tooltiptext { opacity: 1 !important; -} \ No newline at end of file +} diff --git a/pointercrate-demonlist-pages/static/js/modules/statsviewer.js b/pointercrate-demonlist-pages/static/js/modules/statsviewer.js index 6712a66d..35d87a57 100644 --- a/pointercrate-demonlist-pages/static/js/modules/statsviewer.js +++ b/pointercrate-demonlist-pages/static/js/modules/statsviewer.js @@ -104,6 +104,7 @@ export class StatsViewer extends FilteredPaginator { setName(name, nationality) { if (nationality === null) { + this._name.classList.add("name-main-span") this._name.textContent = name; } else { while (this._name.lastChild) { @@ -111,6 +112,7 @@ export class StatsViewer extends FilteredPaginator { } let nameSpan = document.createElement("span"); + nameSpan.classList.add("name-main-span") nameSpan.style.padding = "0 8px"; nameSpan.innerText = name; diff --git a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js index 831e5cc1..74555fb5 100644 --- a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js +++ b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js @@ -170,6 +170,12 @@ $(window).on("load", function () { } }); + document + .getElementById("player-name") + .addEventListener('click', () => + navigator.clipboard.writeText(`https://pointercrate.com/demonlist/statsviewer?player=${window.statsViewer.currentObject.id}`) + ) + new Dropdown(document.getElementById("continent-dropdown")).addEventListener( (selected) => { if (selected === "All") { From 0a332997315d6f43b7eae97bb8f7e28ebf074dac Mon Sep 17 00:00:00 2001 From: sphericle <86196223+sphericle@users.noreply.github.com> Date: Wed, 9 Apr 2025 18:51:58 -0400 Subject: [PATCH 03/12] go to statsviewer --- pointercrate-demonlist-pages/src/account/list_integration.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pointercrate-demonlist-pages/src/account/list_integration.rs b/pointercrate-demonlist-pages/src/account/list_integration.rs index 95687894..56c76d8c 100644 --- a/pointercrate-demonlist-pages/src/account/list_integration.rs +++ b/pointercrate-demonlist-pages/src/account/list_integration.rs @@ -143,6 +143,9 @@ impl AccountPageTab for ListIntegrationTab { span style = "background-color: #D8EFF3" { "Under Consideration" } "." } (paginator("claims-record-pagination", "/api/v1/records/")) + a.button.blue.hover.no-stretch style = "margin: 10px auto 5px;" href = (format!("https://pointercrate.com/demonlist/statsviewer?player={}", claim.player.id)) { + "Go to statsviewer" + } } } } From 63dc21f4ff5cdfce39f1c51b4cc7366e9cf4b015 Mon Sep 17 00:00:00 2001 From: sphericle <86196223+sphericle@users.noreply.github.com> Date: Tue, 27 May 2025 17:13:53 -0400 Subject: [PATCH 04/12] adjust list int. button, add some error handling for banned/nonexistent players --- .../src/account/list_integration.rs | 2 +- .../static/js/statsviewer/individual.js | 24 ++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/pointercrate-demonlist-pages/src/account/list_integration.rs b/pointercrate-demonlist-pages/src/account/list_integration.rs index 56c76d8c..6df6dd47 100644 --- a/pointercrate-demonlist-pages/src/account/list_integration.rs +++ b/pointercrate-demonlist-pages/src/account/list_integration.rs @@ -143,7 +143,7 @@ impl AccountPageTab for ListIntegrationTab { span style = "background-color: #D8EFF3" { "Under Consideration" } "." } (paginator("claims-record-pagination", "/api/v1/records/")) - a.button.blue.hover.no-stretch style = "margin: 10px auto 5px;" href = (format!("https://pointercrate.com/demonlist/statsviewer?player={}", claim.player.id)) { + a.button.blue.hover.no-stretch style = "margin: 10px 37% 5px;" href = (format!("/demonlist/statsviewer?player={}", claim.player.id)) target = "_blank" { "Go to statsviewer" } } diff --git a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js index 74555fb5..87f9c165 100644 --- a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js +++ b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js @@ -1,4 +1,4 @@ -import { Dropdown } from "/static/core/js/modules/form.js"; +import { displayError, Dropdown, get } from "/static/core/js/modules/form.js"; import { getCountryFlag, populateSubdivisionDropdown, @@ -143,6 +143,16 @@ class IndividualStatsViewer extends StatsViewer { }) ); } + + selectPlayerByID(id) { + return get(this.retrievalEndpoint + parseInt(id) + "/").then((data) => { + if (data.data.data.banned) { // wtf + this.setError("This player is banned!") + return; + } + this.onReceive(data); + }); + } } $(window).on("load", function () { @@ -166,14 +176,22 @@ $(window).on("load", function () { let params = new URLSearchParams(url.split('?')[1]); let playerId = params.get('player'); if (playerId) { - window.statsViewer.selectArbitrary(playerId) + window.statsViewer.selectPlayerByID(playerId) + .catch((err) => { + displayError(window.statsViewer)(err) + + // set the URL bar's value to the same location, but with the "player" parameter removed + params.delete("player"); + const urlWithoutParam = `${window.location.origin}${window.location.pathname}?${params.toString()}` + window.history.replaceState({}, '', urlWithoutParam) + }) } }); document .getElementById("player-name") .addEventListener('click', () => - navigator.clipboard.writeText(`https://pointercrate.com/demonlist/statsviewer?player=${window.statsViewer.currentObject.id}`) + navigator.clipboard.writeText(`${window.location.href}?player=${window.statsViewer.currentObject.id}`) ) new Dropdown(document.getElementById("continent-dropdown")).addEventListener( From ddbaed6fbb89dfc26a675425770c2b8db4a8c1e9 Mon Sep 17 00:00:00 2001 From: sphericle <86196223+sphericle@users.noreply.github.com> Date: Wed, 28 May 2025 16:16:04 -0500 Subject: [PATCH 05/12] Fix statsviewer hover styling Co-authored-by: Patrick <43299462+stadust@users.noreply.github.com> --- pointercrate-demonlist-pages/static/css/statsviewer.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pointercrate-demonlist-pages/static/css/statsviewer.css b/pointercrate-demonlist-pages/static/css/statsviewer.css index 05871192..ed612bf8 100644 --- a/pointercrate-demonlist-pages/static/css/statsviewer.css +++ b/pointercrate-demonlist-pages/static/css/statsviewer.css @@ -51,7 +51,7 @@ .name-main-span:hover { cursor: pointer; - text-decoration: underline; + border-bottom: 1px dotted #555; } .tooltip:hover .tooltiptext { From 3890245804fbd7e975e7eb6db45c8601bb29d1e8 Mon Sep 17 00:00:00 2001 From: sphericle <86196223+sphericle@users.noreply.github.com> Date: Wed, 28 May 2025 17:42:21 -0400 Subject: [PATCH 06/12] remove banned users stuff, add link to statsviewer from records list --- pointercrate-demonlist-pages/src/demon_page.rs | 7 +------ .../static/js/statsviewer/individual.js | 17 ++++------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/pointercrate-demonlist-pages/src/demon_page.rs b/pointercrate-demonlist-pages/src/demon_page.rs index 62cdecf3..34583e07 100644 --- a/pointercrate-demonlist-pages/src/demon_page.rs +++ b/pointercrate-demonlist-pages/src/demon_page.rs @@ -424,12 +424,7 @@ impl DemonPage { } } td { - @if let Some(ref video) = record.video { - a href = (video) target = "_blank"{ - (record.player.name) - } - } - @else { + a href = {"/demonlist/statsviewer?player="(record.player.id)} target = "_blank" { (record.player.name) } } diff --git a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js index 87f9c165..ee231537 100644 --- a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js +++ b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js @@ -143,16 +143,6 @@ class IndividualStatsViewer extends StatsViewer { }) ); } - - selectPlayerByID(id) { - return get(this.retrievalEndpoint + parseInt(id) + "/").then((data) => { - if (data.data.data.banned) { // wtf - this.setError("This player is banned!") - return; - } - this.onReceive(data); - }); - } } $(window).on("load", function () { @@ -174,13 +164,14 @@ $(window).on("load", function () { window.statsViewer.initialize().then(() => { let url = window.location.href; let params = new URLSearchParams(url.split('?')[1]); - let playerId = params.get('player'); + let playerId = parseInt(params.get('player')); if (playerId) { - window.statsViewer.selectPlayerByID(playerId) + window.statsViewer.selectArbitrary(playerId) .catch((err) => { displayError(window.statsViewer)(err) - // set the URL bar's value to the same location, but with the "player" parameter removed + // if the param failed, set the URL bar's value to the same location, but with the + // "player" parameter removed params.delete("player"); const urlWithoutParam = `${window.location.origin}${window.location.pathname}?${params.toString()}` window.history.replaceState({}, '', urlWithoutParam) From 40b9d0e1b87006707fbc412fdd8d04dad6d36397 Mon Sep 17 00:00:00 2001 From: sphericle <86196223+sphericle@users.noreply.github.com> Date: Thu, 29 May 2025 22:09:24 -0400 Subject: [PATCH 07/12] add record video to percentage column --- pointercrate-core-pages/static/css/ui.css | 20 +++++++++++++++++++ .../src/demon_page.rs | 8 +++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/pointercrate-core-pages/static/css/ui.css b/pointercrate-core-pages/static/css/ui.css index 950512fd..836c5df8 100644 --- a/pointercrate-core-pages/static/css/ui.css +++ b/pointercrate-core-pages/static/css/ui.css @@ -46,6 +46,26 @@ a.link:after { text-decoration: none; } +@media (max-width: 768px) { + a.mobile-only-link { + color: blue; + } + + a.mobile-only-link:after { + font-family: "Font Awesome 5 Free"; + font-weight: 600; + font-style: normal; + display: inline-block; + text-decoration: inherit; + margin: auto 3px; + } + + a.mobile-only-link:after { + content: "\f35d"; + text-decoration: none; + } +} + /* Default header styles */ body, diff --git a/pointercrate-demonlist-pages/src/demon_page.rs b/pointercrate-demonlist-pages/src/demon_page.rs index 34583e07..6f19755b 100644 --- a/pointercrate-demonlist-pages/src/demon_page.rs +++ b/pointercrate-demonlist-pages/src/demon_page.rs @@ -429,7 +429,13 @@ impl DemonPage { } } td { - (record.progress) "%" + @if let Some(ref video) = record.video { + a.mobile-only-link href = (video) target = "_blank" { + (record.progress) "%" + } + } @else { + (record.progress) "%" + } } td.video-link { @if let Some(ref video) = record.video { From 3fbcb2dc3fc3ace1567a171ad117219139d5d00f Mon Sep 17 00:00:00 2001 From: sphericle <86196223+sphericle@users.noreply.github.com> Date: Thu, 29 May 2025 22:20:05 -0400 Subject: [PATCH 08/12] append player parameter to URL bar on player select --- .../static/js/statsviewer/individual.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js index ee231537..1b7f1204 100644 --- a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js +++ b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js @@ -143,6 +143,13 @@ class IndividualStatsViewer extends StatsViewer { }) ); } + onSelect(selected) { + let params = new URLSearchParams(window.location.href.split('?')[1]); + params.set("player", selected.dataset.id); + const urlWithoutParam = `${window.location.origin}${window.location.pathname}?${params.toString()}` + window.history.replaceState({}, '', urlWithoutParam); + super.onSelect(selected); + } } $(window).on("load", function () { From e5a9fd15a61eafbd17d88a7683c2bb0ca2d9547e Mon Sep 17 00:00:00 2001 From: stadust <43299462+stadust@users.noreply.github.com> Date: Fri, 30 May 2025 07:50:51 +0100 Subject: [PATCH 09/12] fix: display error message if ?player=0 on statsviewer zero is false-y, so it was triggering the path for "malformed player id". Does not really make a difference because there will never be a player with id 0, but oh well. Signed-off-by: stadust <43299462+stadust@users.noreply.github.com> --- .../static/js/statsviewer/individual.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js index 1b7f1204..efcccf4a 100644 --- a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js +++ b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js @@ -172,7 +172,7 @@ $(window).on("load", function () { let url = window.location.href; let params = new URLSearchParams(url.split('?')[1]); let playerId = parseInt(params.get('player')); - if (playerId) { + if (playerId !== undefined && !isNaN(playerId)) { window.statsViewer.selectArbitrary(playerId) .catch((err) => { displayError(window.statsViewer)(err) From a3cc5c5e5cc25d9e9db58edf65e1f0f07bed80c2 Mon Sep 17 00:00:00 2001 From: stadust <43299462+stadust@users.noreply.github.com> Date: Fri, 30 May 2025 07:59:32 +0100 Subject: [PATCH 10/12] js: reset pagination error message on selection and navigation Otherwise it'll just stick around forever, which is a bit annoying if someone clicks a stats viewer link for a non-existing player. Signed-off-by: stadust <43299462+stadust@users.noreply.github.com> --- pointercrate-core-pages/static/js/modules/form.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pointercrate-core-pages/static/js/modules/form.js b/pointercrate-core-pages/static/js/modules/form.js index 3b4eb7b4..ecb547db 100644 --- a/pointercrate-core-pages/static/js/modules/form.js +++ b/pointercrate-core-pages/static/js/modules/form.js @@ -493,8 +493,10 @@ export class Paginator extends Output { * @returns A promise */ selectArbitrary(id) { - return get(this.retrievalEndpoint + id + "/").then( - this.onReceive.bind(this) + return get(this.retrievalEndpoint + id + "/").then(response => { + this.setError(null); + this.onReceive(response); + } ); } @@ -608,6 +610,7 @@ export class Paginator extends Output { * @memberof Paginator */ refresh() { + this.setError(null); return get(this.currentLink) .then(this.handleResponse.bind(this)) .catch(displayError(this)); @@ -615,6 +618,7 @@ export class Paginator extends Output { onPreviousClick() { if (this.links.prev) { + this.setError(null); get(this.links.prev) .then(this.handleResponse.bind(this)) .catch(displayError(this)); @@ -623,6 +627,7 @@ export class Paginator extends Output { onNextClick() { if (this.links.next) { + this.setError(null); get(this.links.next) .then(this.handleResponse.bind(this)) .catch(displayError(this)); From 8b9f4451e3ee0486f5a6e136088652e6cc6372d3 Mon Sep 17 00:00:00 2001 From: stadust <43299462+stadust@users.noreply.github.com> Date: Fri, 30 May 2025 17:46:46 +0100 Subject: [PATCH 11/12] minor cleanups - remove copy-to-clipboard when clicking player name. The on-hover underlining was causing the flags to resize, and now that the URL gets updated, one can just copy the link from the browser (which is a bit more intuitive imo, as nothing was really indicating that the clipboard functionality was there, or that "add to clipboard" was actually what happened when the name was clicked) - Gave small visual indication that player names on demon pages can be clicked by underlining them. Signed-off-by: stadust <43299462+stadust@users.noreply.github.com> --- pointercrate-core-pages/static/css/ui.css | 5 ++++- pointercrate-demonlist-pages/src/demon_page.rs | 2 +- pointercrate-demonlist-pages/static/css/statsviewer.css | 5 ----- .../static/js/modules/statsviewer.js | 2 -- .../static/js/statsviewer/individual.js | 6 ------ 5 files changed, 5 insertions(+), 15 deletions(-) diff --git a/pointercrate-core-pages/static/css/ui.css b/pointercrate-core-pages/static/css/ui.css index 836c5df8..80902ce1 100644 --- a/pointercrate-core-pages/static/css/ui.css +++ b/pointercrate-core-pages/static/css/ui.css @@ -595,7 +595,6 @@ h2 .dropdown-menu ul { .tooltip { position: relative; display: inline-block; - border-bottom: 1px dotted #555; } .tooltip .tooltiptext { @@ -658,6 +657,10 @@ h2 .dropdown-menu ul { padding-top: 10px; } +.underdotted { + border-bottom: 1px dotted #555; +} + .info-green { background: #ddffdd; border: 1px solid #a8ff93; diff --git a/pointercrate-demonlist-pages/src/demon_page.rs b/pointercrate-demonlist-pages/src/demon_page.rs index 6f19755b..7dac328b 100644 --- a/pointercrate-demonlist-pages/src/demon_page.rs +++ b/pointercrate-demonlist-pages/src/demon_page.rs @@ -424,7 +424,7 @@ impl DemonPage { } } td { - a href = {"/demonlist/statsviewer?player="(record.player.id)} target = "_blank" { + a.underdotted href = {"/demonlist/statsviewer?player="(record.player.id)} target = "_blank" { (record.player.name) } } diff --git a/pointercrate-demonlist-pages/static/css/statsviewer.css b/pointercrate-demonlist-pages/static/css/statsviewer.css index ed612bf8..d7ced2ed 100644 --- a/pointercrate-demonlist-pages/static/css/statsviewer.css +++ b/pointercrate-demonlist-pages/static/css/statsviewer.css @@ -49,11 +49,6 @@ flex-grow: 2; } -.name-main-span:hover { - cursor: pointer; - border-bottom: 1px dotted #555; -} - .tooltip:hover .tooltiptext { opacity: 1 !important; } diff --git a/pointercrate-demonlist-pages/static/js/modules/statsviewer.js b/pointercrate-demonlist-pages/static/js/modules/statsviewer.js index 35d87a57..6712a66d 100644 --- a/pointercrate-demonlist-pages/static/js/modules/statsviewer.js +++ b/pointercrate-demonlist-pages/static/js/modules/statsviewer.js @@ -104,7 +104,6 @@ export class StatsViewer extends FilteredPaginator { setName(name, nationality) { if (nationality === null) { - this._name.classList.add("name-main-span") this._name.textContent = name; } else { while (this._name.lastChild) { @@ -112,7 +111,6 @@ export class StatsViewer extends FilteredPaginator { } let nameSpan = document.createElement("span"); - nameSpan.classList.add("name-main-span") nameSpan.style.padding = "0 8px"; nameSpan.innerText = name; diff --git a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js index efcccf4a..776dac9d 100644 --- a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js +++ b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js @@ -186,12 +186,6 @@ $(window).on("load", function () { } }); - document - .getElementById("player-name") - .addEventListener('click', () => - navigator.clipboard.writeText(`${window.location.href}?player=${window.statsViewer.currentObject.id}`) - ) - new Dropdown(document.getElementById("continent-dropdown")).addEventListener( (selected) => { if (selected === "All") { From 6dd8e251d5a55bbb8a55c0a850e07e8a94a6e461 Mon Sep 17 00:00:00 2001 From: stadust <43299462+stadust@users.noreply.github.com> Date: Fri, 30 May 2025 17:48:25 +0100 Subject: [PATCH 12/12] ui: display rank as '-' for unranked players By using direct stats viewer links, its possible to pull up players that have no score, and hence no rank. Display rank as '-' for these. Signed-off-by: stadust <43299462+stadust@users.noreply.github.com> --- .../static/js/statsviewer/individual.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js index 776dac9d..3c4fd15e 100644 --- a/pointercrate-demonlist-pages/static/js/statsviewer/individual.js +++ b/pointercrate-demonlist-pages/static/js/statsviewer/individual.js @@ -23,7 +23,7 @@ class IndividualStatsViewer extends StatsViewer { var playerData = response.data.data; - this._rank.innerText = playerData.rank; + this._rank.innerText = playerData.rank || "-"; this._score.innerText = playerData.score.toFixed(2); this.setName(playerData.name, playerData.nationality);