diff --git a/bbb-learning-dashboard/src/App.js b/bbb-learning-dashboard/src/App.js index a063f098ff..2a9cc03763 100644 --- a/bbb-learning-dashboard/src/App.js +++ b/bbb-learning-dashboard/src/App.js @@ -128,6 +128,7 @@ class App extends React.Component { // Get the three most used const mostUsedEmojis = Object .entries(emojiCount) + .filter(([, count]) => count) .sort(([, countA], [, countB]) => countA - countB) .reverse() .slice(0, 3); @@ -452,7 +453,7 @@ class App extends React.Component { ? : null } { tab === 'polling' - ? + ? : null }
@@ -482,7 +483,7 @@ class App extends React.Component {

-
+

{ diff --git a/bbb-learning-dashboard/src/components/PollsTable.jsx b/bbb-learning-dashboard/src/components/PollsTable.jsx index b04eab1e09..8d60d406aa 100644 --- a/bbb-learning-dashboard/src/components/PollsTable.jsx +++ b/bbb-learning-dashboard/src/components/PollsTable.jsx @@ -18,7 +18,7 @@ class PollsTable extends React.Component { if (typeof polls === 'object' && Object.values(polls).length === 0) { return ( -

+
+ + + ); +} + class UsersTable extends React.Component { constructor(props) { super(props); this.state = { + userOrder: 'asc', + onlineTimeOrder: 'desc', + talkTimeOrder: 'desc', + webcamTimeOrder: 'desc', activityscoreOrder: 'desc', + lastFieldClicked: 'userOrder', }; } - toggleActivityScoreOrder() { - const { activityscoreOrder } = this.state; + toggleOrder(field) { + const { [field]: fieldOrder } = this.state; + const { tab } = this.props; - if (activityscoreOrder === 'asc') { - this.setState({ activityscoreOrder: 'desc' }); + if (fieldOrder === 'asc') { + this.setState({ [field]: 'desc' }); } else { - this.setState({ activityscoreOrder: 'asc' }); + this.setState({ [field]: 'asc' }); } + + if (tab === 'overview') this.setState({ lastFieldClicked: field }); } render() { @@ -29,7 +56,10 @@ class UsersTable extends React.Component { allUsers, totalOfActivityTime, totalOfPolls, tab, } = this.props; - const { activityscoreOrder } = this.state; + const { + activityscoreOrder, userOrder, onlineTimeOrder, + talkTimeOrder, webcamTimeOrder, lastFieldClicked, + } = this.state; const usersEmojisSummary = {}; Object.values(allUsers || {}).forEach((user) => { @@ -46,36 +76,120 @@ class UsersTable extends React.Component { usersActivityScore[user.userKey] = getActivityScore(user, allUsers, totalOfPolls); }); + const sortFunctions = { + userOrder(a, b) { + if (a.name.toLowerCase() < b.name.toLowerCase()) { + return userOrder === 'desc' ? 1 : -1; + } + if (a.name.toLowerCase() > b.name.toLowerCase()) { + return userOrder === 'desc' ? -1 : 1; + } + return 0; + }, + onlineTimeOrder(a, b) { + const onlineTimeA = Object.values(a.intIds).reduce((prev, intId) => ( + prev + ((intId.leftOn > 0 + ? intId.leftOn + : (new Date()).getTime()) - intId.registeredOn) + ), 0); + + const onlineTimeB = Object.values(b.intIds).reduce((prev, intId) => ( + prev + ((intId.leftOn > 0 + ? intId.leftOn + : (new Date()).getTime()) - intId.registeredOn) + ), 0); + + if (onlineTimeA < onlineTimeB) { + return onlineTimeOrder === 'desc' ? 1 : -1; + } + + if (onlineTimeA > onlineTimeB) { + return onlineTimeOrder === 'desc' ? -1 : 1; + } + + return 0; + }, + talkTimeOrder(a, b) { + const talkTimeA = a.talk.totalTime; + const talkTimeB = b.talk.totalTime; + + if (talkTimeA < talkTimeB) { + return onlineTimeOrder === 'desc' ? 1 : -1; + } + + if (talkTimeA > talkTimeB) { + return onlineTimeOrder === 'desc' ? -1 : 1; + } + + return 0; + }, + webcamTimeOrder(a, b) { + const webcamTimeA = getSumOfTime(a.webcams); + const webcamTimeB = getSumOfTime(b.webcams); + console.log(webcamTimeA, webcamTimeB); + + if (webcamTimeA < webcamTimeB) { + return onlineTimeOrder === 'desc' ? 1 : -1; + } + + if (webcamTimeA > webcamTimeB) { + return onlineTimeOrder === 'desc' ? -1 : 1; + } + + return 0; + }, + activityscoreOrder(a, b) { + if (usersActivityScore[a.userKey] < usersActivityScore[b.userKey]) { + return activityscoreOrder === 'desc' ? 1 : -1; + } + if (usersActivityScore[a.userKey] > usersActivityScore[b.userKey]) { + return activityscoreOrder === 'desc' ? -1 : 1; + } + if (a.isModerator === false && b.isModerator === true) return 1; + if (a.isModerator === true && b.isModerator === false) return -1; + return 0; + }, + }; + return ( - - - - { typeof allUsers === 'object' && Object.values(allUsers || {}).length > 0 ? ( Object.values(allUsers || {}) - .sort((a, b) => { - if (tab === 'overview_activityscore' && usersActivityScore[a.userKey] < usersActivityScore[b.userKey]) { - return activityscoreOrder === 'desc' ? 1 : -1; - } - if (tab === 'overview_activityscore' && usersActivityScore[a.userKey] > usersActivityScore[b.userKey]) { - return activityscoreOrder === 'desc' ? -1 : 1; - } - if (a.isModerator === false && b.isModerator === true) return 1; - if (a.isModerator === true && b.isModerator === false) return -1; - if (a.name.toLowerCase() < b.name.toLowerCase()) return -1; - if (a.name.toLowerCase() > b.name.toLowerCase()) return 1; - return 0; - }) + .sort(tab === 'overview' ? sortFunctions[lastFieldClicked] : sortFunctions.activityscoreOrder) .map((user) => { const opacity = user.leftOn > 0 ? 'opacity-75' : ''; return ( @@ -383,7 +468,11 @@ class UsersTable extends React.Component { - ) : + ) }
+ { if (tab === 'overview') this.toggleOrder('userOrder'); }} + > - { - tab === 'overview' - ? ( - - - - ) - : null - } + { tab === 'overview' && lastFieldClicked === 'userOrder' + ? renderArrow(userOrder) + : null } + { if (tab === 'overview') this.toggleOrder('onlineTimeOrder'); }} + > + { tab === 'overview' && lastFieldClicked === 'onlineTimeOrder' + ? renderArrow(onlineTimeOrder) + : null } + { if (tab === 'overview') this.toggleOrder('talkTimeOrder'); }} + > + { tab === 'overview' && lastFieldClicked === 'talkTimeOrder' + ? renderArrow(talkTimeOrder) + : null } + { if (tab === 'overview') this.toggleOrder('webcamTimeOrder'); }} + > + { tab === 'overview' && lastFieldClicked === 'webcamTimeOrder' + ? renderArrow(webcamTimeOrder) + : null } @@ -88,29 +202,12 @@ class UsersTable extends React.Component { { if (tab === 'overview_activityscore') this.toggleActivityScoreOrder(); }} + onClick={() => { if (tab === 'overview_activityscore') this.toggleOrder('activityscoreOrder'); }} > - { - tab === 'overview_activityscore' - ? ( - - - - ) - : null - } + { tab === 'overview_activityscore' + ? renderArrow(activityscoreOrder) + : null } @@ -120,19 +217,7 @@ class UsersTable extends React.Component {
+ ) : ( + + + { diff --git a/bigbluebutton-html5/public/locales/en.json b/bigbluebutton-html5/public/locales/en.json index 5d4f254718..8fba4d3911 100755 --- a/bigbluebutton-html5/public/locales/en.json +++ b/bigbluebutton-html5/public/locales/en.json @@ -985,7 +985,8 @@ "app.learningDashboard.usersTable.pollVotes": "Poll Votes", "app.learningDashboard.usersTable.join": "Join", "app.learningDashboard.usersTable.left": "Left", - "app.learningDashboard.pollsTable.title": "Polling", + "app.learningDashboard.usersTable.notAvailable": "N/A", + "app.learningDashboard.pollsTable.title": "Polls", "app.learningDashboard.pollsTable.anonymousAnswer": "Anonymous Poll (answers in the last row)", "app.learningDashboard.pollsTable.anonymousRowName": "Anonymous", "app.learningDashboard.pollsTable.noPollsCreatedHeading": "No polls have been created",