diff --git a/apiserver/apiserver/api/management/commands/run_minutely.py b/apiserver/apiserver/api/management/commands/run_minutely.py index 890b4a0..a2def88 100644 --- a/apiserver/apiserver/api/management/commands/run_minutely.py +++ b/apiserver/apiserver/api/management/commands/run_minutely.py @@ -14,6 +14,8 @@ class Command(BaseCommand): players = utils_stats.check_minecraft_server() self.stdout.write('Found Minecraft players: ' + str(players)) + users = utils_stats.check_mumble_server() + self.stdout.write('Found Mumble users: ' + str(users)) self.stdout.write('Completed tasks in {} s'.format( str(time.time() - start)[:4] diff --git a/apiserver/apiserver/api/utils_stats.py b/apiserver/apiserver/api/utils_stats.py index fff9baf..67c4b7b 100644 --- a/apiserver/apiserver/api/utils_stats.py +++ b/apiserver/apiserver/api/utils_stats.py @@ -22,6 +22,7 @@ DEFAULTS = { 'bay_108_temp': None, 'bay_110_temp': None, 'minecraft_players': [], + 'mumble_users': [], 'card_scans': 0, 'track': {}, } @@ -114,6 +115,21 @@ def check_minecraft_server(): return [] +def check_mumble_server(): + if secrets.MUMBLE: + url = secrets.MUMBLE + + try: + r = requests.get(url, timeout=5) + r.raise_for_status() + users = r.text.split() + cache.set('mumble_users', users) + return users + except BaseException as e: + logger.error('Problem checking Mumble: {} - {}'.format(e.__class__.__name__, str(e))) + + return [] + def calc_card_scans(): date = today_alberta_tz() cards = models.Card.objects diff --git a/apiserver/apiserver/secrets.py.example b/apiserver/apiserver/secrets.py.example index c4da972..df16488 100644 --- a/apiserver/apiserver/secrets.py.example +++ b/apiserver/apiserver/secrets.py.example @@ -60,6 +60,7 @@ DOOR_API_TOKEN = '' DOOR_CODE = '' WIFI_PASS = '' MINECRAFT = '' +MUMBLE = '' # Portal Email Credentials # For sending password resets, etc. diff --git a/webclient/src/AdminMembers.js b/webclient/src/AdminMembers.js index 32ba9c8..99d906b 100644 --- a/webclient/src/AdminMembers.js +++ b/webclient/src/AdminMembers.js @@ -221,7 +221,15 @@ export function AdminMemberCards(props) { /> - + + + Submit {success &&
Success!
} diff --git a/webclient/src/App.js b/webclient/src/App.js index 9a5dcc3..2172b72 100644 --- a/webclient/src/App.js +++ b/webclient/src/App.js @@ -2,6 +2,7 @@ import React, { useState, useEffect, useReducer, useContext } from 'react'; import { BrowserRouter as Router, Switch, Route, Link, useParams, useHistory } from 'react-router-dom'; import './semantic-ui/semantic.min.css'; import './light.css'; +import './dark.css'; import { Container, Divider, Dropdown, Form, Grid, Header, Icon, Image, Menu, Message, Segment, Table } from 'semantic-ui-react'; import Darkmode from 'darkmode-js'; import { isAdmin, requester } from './utils.js'; diff --git a/webclient/src/Charts.js b/webclient/src/Charts.js index 7f3c76b..7a9aca9 100644 --- a/webclient/src/Charts.js +++ b/webclient/src/Charts.js @@ -47,6 +47,25 @@ export function Charts(props) {
Charts
+
Summary
+ + {memberCount && signupCount && + <> +

+ The total member count is {memberCount.slice().reverse()[0].member_count} members, + compared to {memberCount.slice().reverse()[30].member_count} members 30 days ago. +

+

+ The green member count is {memberCount.slice().reverse()[0].green_count} members, + compared to {memberCount.slice().reverse()[30].green_count} members 30 days ago. +

+

+ There were {signupCount.slice().reverse()[0].signup_count} signups so far this month, + and {signupCount.slice().reverse()[1].signup_count} signups last month. +

+ + } +
Member Counts

Daily since March 2nd, 2020.

diff --git a/webclient/src/Home.js b/webclient/src/Home.js index 7c34a13..0d25fcf 100644 --- a/webclient/src/Home.js +++ b/webclient/src/Home.js @@ -152,6 +152,7 @@ export function Home(props) { const getDateStat = (x) => stats && stats[x] ? moment.utc(stats[x]).tz('America/Edmonton').format('ll') : '?'; const mcPlayers = stats && stats['minecraft_players'] ? stats['minecraft_players'] : []; + const mumbleUsers = stats && stats['mumble_users'] ? stats['mumble_users'] : []; const getTrackStat = (x) => stats && stats.track && stats.track[x] ? moment().unix() - stats.track[x]['time'] > 60 ? 'Free' : 'In Use' : '?'; const getTrackLast = (x) => stats && stats.track && stats.track[x] ? moment.unix(stats.track[x]['time']).tz('America/Edmonton').format('llll') : 'Unknown'; @@ -214,11 +215,10 @@ export function Home(props) {

Next monthly clean: {getDateStat('next_clean')}

Member count: {getStat('member_count')} [more]

Green members: {getStat('green_count')}

-

Old members: {getStat('paused_count')}

Card scans today: {getZeroStat('card_scans')}

- Minecraft players: {mcPlayers.length} 5 && '🔥'}

Server IP:
@@ -233,6 +233,21 @@ export function Home(props) { {' '}[map]

+

+ Mumble users: {mumbleUsers.length} +

+ Server IP:
+ mumble.protospace.ca +

+

+ Users:
+ {mumbleUsers.length ? mumbleUsers.map(x => {x}
) : 'None'} +

+ + } trigger={[more]} /> +

+

Trotec availability: {getTrackStat('TROTECS300')} diff --git a/webclient/src/dark.css b/webclient/src/dark.css new file mode 100644 index 0000000..c2a53cf --- /dev/null +++ b/webclient/src/dark.css @@ -0,0 +1,57 @@ +.darkmode-layer, .darkmode-toggle { + z-index: 500; +} + +.darkmode--activated .ui.image { + mix-blend-mode: difference; + filter: brightness(75%); +} + +.darkmode--activated i.green.circle.icon { + mix-blend-mode: difference; + color: #21ba4582 !important; + +} + +.darkmode--activated i.yellow.circle.icon { + mix-blend-mode: difference; + color: #fbbd0882 !important; +} + +.darkmode--activated i.red.circle.icon { + mix-blend-mode: difference; + color: #db282882 !important; +} + +.darkmode--activated .footer { + mix-blend-mode: difference; +} + +.darkmode--activated .ql-toolbar.ql-snow, +.darkmode--activated .ql-container.ql-snow, +.darkmode--activated .ui.segment, +.darkmode--activated .ui.form .field input, +.darkmode--activated .ui.form .field .selection.dropdown, +.darkmode--activated .ui.form .field .ui.checkbox label::before, +.darkmode--activated .ui.form .field textarea { + border: 1px solid rgba(34,36,38,.50) !important; +} + +.darkmode--activated .ui.basic.table tbody tr { + border-bottom: 1px solid rgba(34,36,38,.50) !important; +} + +.darkmode--activated .ui.button { + background: #c9c9c9 !important; +} + +.darkmode--activated .ui.red.button { + mix-blend-mode: difference; + background: #db282882 !important; +} + +.darkmode--activated .ui.green.button, +.darkmode--activated .ui.button.toggle.active { + mix-blend-mode: difference; + background: #21ba4582 !important; +} diff --git a/webclient/src/light.css b/webclient/src/light.css index eeddb3b..999c807 100644 --- a/webclient/src/light.css +++ b/webclient/src/light.css @@ -150,23 +150,3 @@ body { margin-left: -3.5px; margin-right: 0.5em; } - - -.darkmode-layer, .darkmode-toggle { - z-index: 500; -} - -.darkmode--activated .ui.image { - mix-blend-mode: difference; - filter: brightness(50%); -} - -.darkmode--activated i.green.circle.icon, -.darkmode--activated i.yellow.circle.icon, -.darkmode--activated i.red.circle.icon { - mix-blend-mode: difference; -} - -.darkmode--activated .footer { - mix-blend-mode: difference; -}