import React, { useState, useEffect, useReducer } from 'react'; import { Link } from 'react-router-dom'; import './light.css'; import { Button, Container, Checkbox, Form, Header, Icon, Table } from 'semantic-ui-react'; import * as Datetime from 'react-datetime'; import moment from 'moment-timezone'; import download from 'downloadjs'; import { apiUrl, statusColor, requester } from './utils.js'; let vettingCache = false; let historyCache = false; let excludeSystemCache = true; let focusCache = false; export function AdminVet(props) { const { token, member, refreshVetting } = props; const [loading, setLoading] = useState(false); const [yousure, setYousure] = useState(false); const handleVet = (e) => { e.preventDefault(); if (yousure) { setLoading(true); const data = {vetted_date: moment.utc().tz('America/Edmonton').format('YYYY-MM-DD')} requester('/members/' + member.id + '/', 'PATCH', token, data) .then(res => { refreshVetting(); }) .catch(err => { console.log(err); }); } else { setYousure(true); } }; return ( ); } export function AdminVetting(props) { const { token } = props; const [vetting, setVetting] = useState(vettingCache); const [refreshCount, refreshVetting] = useReducer(x => x + 1, 0); const [error, setError] = useState(false); const [showAll, setShowAll] = useState(false); useEffect(() => { requester('/vetting/', 'GET', token) .then(res => { setVetting(res.results); vettingCache = res.results; }) .catch(err => { console.log(err); setError(true); }); }, [refreshCount]); const displayAll = (vetting && vetting.length <= 5) || showAll; return (
{!error ? vetting ? <> Name Status / NMO {(displayAll ? vetting : vetting.slice(0,5)).sort((a, b) => a.last_name > b.last_name ? 1 : -1).map(x => {x.preferred_name} {x.last_name} {x.orientation_date ? '✅' : '❌'} )}

{displayAll ? '' : '5 / '}{vetting.length} members

{displayAll ? <> ↳ x.email).join(',')}>Email All : }

:

Loading...

:

Error loading.

}
); } export function AdminHistory(props) { const { token } = props; const [history, setHistory] = useState(historyCache); const [excludeSystem, setExcludeSystem] = useState(excludeSystemCache); const [focus, setFocus] = useState(focusCache); const [error, setError] = useState(false); const handleExcludeSystem = (e, v) => { setExcludeSystem(v.checked); excludeSystemCache = v.checked; }; useEffect(() => { const extra = excludeSystem ? '?exclude_system' : ''; requester('/history/'+extra, 'GET', token) .then(res => { setHistory(res.results); historyCache = res.results; }) .catch(err => { console.log(err); setError(true); }); }, [excludeSystem]); return (
{!error ? history ? <> Date Username Type Owner Object Changed Fields {history.map(x => setFocus(x.id)}> {moment.utc(x.history_date).tz('America/Edmonton').format('YYYY-MM-DD')} {x.is_system ? 'System' : (x.history_user || 'Deleted User')} {x.history_type} {x.owner_name} {x.object_name} {x.changes.map(x => x.field).join(', ')} {focus === x.id && } )}

Object ID: {x.object_id}, Database Revert

{!!x.changes.length && Change Before After {x.changes.map(y => {y.field} {y.old} {y.new} )}
}
:

Loading...

:

Error loading.

}
); }; let backupsCache = false; export function AdminBackups(props) { const [backups, setBackups] = useState(backupsCache); const [error, setError] = useState(false); useEffect(() => { requester('/backup/', 'GET') .then(res => { setBackups(res); backupsCache = res; }) .catch(err => { console.log(err); setError(true); }); }, []); return (
{!error ? backups ? Username Last Downloaded Less than 24 hours ago? {backups.filter(x => x.download_time).map(x => {x.backup_user} {moment.utc(x.download_time).tz('America/Edmonton').format('LLLL')} {x.less_than_24h ? 'Yes' : 'No - please investigate'} )}
:

Loading...

:

Error loading.

}
); }; export function AdminUsage(props) { const { token } = props; const [input, setInput] = useState({ month: moment() }); const [loading, setLoading] = useState(false); const [error, setError] = useState(false); const handleDatetime = (v) => setInput({ ...input, month: v }); const handleDownload = (month) => { if (loading) return; setLoading(true); const query = month ? '?month=' + month : ''; requester('/usage/csv/' + query, 'GET', token) .then(res => { setLoading(false); setError(false); return res.blob(); }) .then(blob => { download(blob, 'usage-'+(month || 'all')+'.csv'); }) .catch(err => { setLoading(false); console.log(err); setError(true); }); }; const handleSubmit = (e) => { const month = input.month.format('YYYY-MM'); handleDownload(month) }; return (
Download
handleDownload(null)}> Download All {error &&

Error.

}
); }; export function Admin(props) { return (
Portal Admin
Ready to Vet

Members who are Current or Due, and past their probationary period.

Sorted by last name.

Member Data Backup

Spaceport backups are created daily. 14 days are kept on the server.

Backup Downloads
Trotec Device Usage

All times are in Mountain time.

History

Last 50 database changes:

); };