From 6f2aae81731a15b65a53bcddd8654e9b03b7e5c3 Mon Sep 17 00:00:00 2001 From: "H. Ryan Jones" Date: Sun, 11 Aug 2019 13:09:27 -0700 Subject: [PATCH] Allow sorting of the leaderboard. --- board.html | 26 ++++++++++++++++++++---- index.css | 7 ++++++- index.html | 21 ++++++++++++-------- index.js | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 98 insertions(+), 14 deletions(-) diff --git a/board.html b/board.html index a8a9681..8d98296 100644 --- a/board.html +++ b/board.html @@ -30,9 +30,20 @@

Completion board for "{{difficulty}}" today

- - - + @@ -72,10 +83,16 @@

Completion board for "{{difficulty}}" today

new Vue({ el: '#leaderboard-container', data: { + LEADER_HEADER_FIELDS, leaders: [], difficulty: 'normal', message: '', error: '', + sortConfig: { + key: 'numberOfGuesses', + sortKey: 'numberOfGuesses', + direction: 'ascending', + }, }, created() { this.getLeaders(); @@ -86,7 +103,8 @@

Completion board for "{{difficulty}}" today

const newDifficulty = e.target.value; this.difficulty = newDifficulty; this.getLeaders(); - } + }, + changeLeaderSort, }, }); diff --git a/index.css b/index.css index 91fb70f..9f6512f 100644 --- a/index.css +++ b/index.css @@ -218,7 +218,6 @@ form { th { - text-align: left; border-bottom: 1px solid black; background-color: white; } @@ -226,6 +225,12 @@ th { thead, th { position: sticky; top: 0px; + cursor: pointer; +} + +.leader-table-header-cell { + display: flex; + justify-content: space-between; } td { diff --git a/index.html b/index.html index 2150460..c4e95cf 100644 --- a/index.html +++ b/index.html @@ -88,18 +88,23 @@

Completion board for

nametotal guessestime +
+
{{field.text}}
+
+ {{sortConfig.direction === 'descending' ? '▾' : '▴'}} +
+
+
- - - - - - - + + + + + - +
nametotal guessestime
+
+
{{field.text}}
+
+ {{sortConfig.direction === 'descending' ? '▾' : '▴'}} +
+
+
{{leader.name}} {{leader.numberOfGuesses}}{{getFormattedTime(leader.time)}}{{leader.formattedTime}}
diff --git a/index.js b/index.js index 663801a..acd14ed 100644 --- a/index.js +++ b/index.js @@ -20,18 +20,31 @@ let vueApp; const UNKNOWN_LEADERBOARD_ERROR = "Sorry, can't contact the leaderboard right now. Please try again in a little bit. (please contact @hryanjones if it persists)"; +const LEADER_HEADER_FIELDS = [ + { text: 'name', key: 'name', sortKey: 'name' }, + { text: '# guesses', key: 'numberOfGuesses', sortKey: 'numberOfGuesses' }, + { text: 'time', key: 'formattedTime', sortKey: 'time' }, +]; + document.addEventListener('DOMContentLoaded', () => { if (getElement('container')) { vueApp = new Vue({ el: '#container', data: { + LEADER_HEADER_FIELDS, leaders: [], + sortConfig: { + key: 'numberOfGuesses', + sortKey: 'numberOfGuesses', + direction: 'ascending', + }, }, methods: { submitToLeaderboard, reset() { this.leaders = []; - } + }, + changeLeaderSort, }, }); } @@ -458,3 +471,46 @@ function sortByGuessesThenTime(leader1, leader2) { } return 0; } + +const OPPOSITE_SORT_DIRECTION = { + ascending: 'descending', + descending: 'ascending', +}; + +function changeLeaderSort(newKey, newSortKey) { + let {direction, key, sortKey} = this.sortConfig; + if (newKey === this.sortConfig.key) { + direction = OPPOSITE_SORT_DIRECTION[direction]; + } else { + key = newKey; + sortKey = newSortKey || newKey; + } + + this.sortConfig = { direction, key, sortKey }; + + this.leaders = sortLeaders(this.leaders, sortKey, direction); +} + +function sortLeaders(leaders, sortKey, direction) { + return sortArrayByKey(leaders, sortKey, direction); +} + +function sortArrayByKey(array, key, direction) { + const sorter = direction === 'descending' ? sortByKeyDesc : sortByKeyAsc; + array = array.slice(0); + return array.sort(sorter); + + function sortByKeyAsc(first, second) { + if (first[key] > second[key]) { + return 1; + } + if (first[key] < second[key]) { + return -1; + } + return 0; + } + + function sortByKeyDesc(first, second) { + return -1 * sortByKeyAsc(first, second); + } +}