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, useIsMobile } 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, filterMember } = props; const [history, setHistory] = useState(historyCache); const [excludeSystem, setExcludeSystem] = useState(excludeSystemCache); const [focus, setFocus] = useState(focusCache); const [error, setError] = useState(false); const isMobile = useIsMobile(); const handleExcludeSystem = (e, v) => { setExcludeSystem(v.checked); excludeSystemCache = v.checked; }; useEffect(() => { let extra = '?exclude_system=' + excludeSystem; if (filterMember) { extra += '&member_id=' + filterMember; } requester('/history/'+extra, 'GET', token) .then(res => { setHistory(res.results); historyCache = res.results; }) .catch(err => { console.log(err); setError(true); }); }, [excludeSystem]); return (
{!error ? history ? <>
History

Last 50 database changes:

{!isMobile && Date Username Type {!filterMember && Owner} Object Changed Fields } {!history.length &&

None

} {history.map(x => setFocus(x.id)}> {moment.utc(x.history_date).tz('America/Edmonton').format('YYYY-MM-DD')} {isMobile && 'User: '}{x.is_system ? 'System' : (x.history_user || 'Deleted User')} {isMobile && 'Type: '}{x.history_type} {!filterMember && {isMobile && 'Owner: '}{x.owner_name}} {isMobile && 'Object: '}{x.object_name} {isMobile && 'Changed: '}{x.changes.map(x => x.field).join(', ')} {focus === x.id &&
} )}

Object ID: {x.object_id}, Database Revert

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

Loading...

:

Error loading.

}
); }; let backupsCache = false; export function AdminBackups(props) { const [backups, setBackups] = useState(backupsCache); const [error, setError] = useState(false); const isMobile = useIsMobile(); useEffect(() => { requester('/backup/', 'GET') .then(res => { setBackups(res); backupsCache = res; }) .catch(err => { console.log(err); setError(true); }); }, []); return (
{!error ? backups ? {!isMobile && Username Last Downloaded Less than 24 hours ago? } {backups.filter(x => x.download_time).map(x => {isMobile && 'User: '}{x.backup_user} {isMobile && 'Last: '}{moment.utc(x.download_time).tz('America/Edmonton').format('LLLL')} {isMobile && '24h ago: '}{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.

); };