better code: typing
Massimo Melina committed
May 3, 2023 at 09:57 UTC
0b51c0d5bc0c1a1ba596dc1d4cd24c3bf9052287
2 files changed
+9
-6
admin/src/HomePage.ts
+8
-5
@@ -3,7 +3,7 @@
3
import { createElement as h } from 'react'
4
import { Box, Button, LinearProgress, Link } from '@mui/material'
5
import { apiCall, useApi, useApiEx, useApiList } from './api'
6
-import { Dict, dontBotherWithKeys, InLink, objSameKeys, onlyTruthy } from './misc'
6
+import { dontBotherWithKeys, InLink, objSameKeys, onlyTruthy } from './misc'
7
import { CheckCircle, Error, Info, Launch, Warning } from '@mui/icons-material'
8
import md from './md'
9
import { useSnapState } from './state'
@@ -11,15 +11,17 @@ import { confirmDialog } from './dialog'
11
import { isCertError, isKeyError, makeCertAndSave } from './OptionsPage'
12
import { VfsNode } from './VfsPage'
13
import { Account } from './AccountsPage'
14
+import _ from 'lodash'
15
16
export const REPO_URL = 'https://github.com/rejetto/hfs/'
17
18
interface ServerStatus { listening: boolean, port: number, error?: string, busy?: string }
19
+interface Status { http: ServerStatus, https: ServerStatus, frpDetected: boolean }
20
21
export default function HomePage() {
22
const SOLUTION_SEP = " — "
23
const { username } = useSnapState()
22
- const { data: status, reload: reloadStatus, element: statusEl } = useApiEx<Dict<ServerStatus>>('get_status')
24
+ const { data: status, reload: reloadStatus, element: statusEl } = useApiEx<Status>('get_status')
25
const { data: vfs } = useApiEx<{ root?: VfsNode }>('get_vfs')
26
const [account] = useApi<Account>(username && 'get_account')
27
const { data: cfg, reload: reloadCfg } = useApiEx('get_config', { only: ['https_port', 'cert', 'private_key', 'proxies'] })
@@ -30,10 +32,11 @@ export default function HomePage() {
32
const goSecure = !http?.listening && https?.listening ? 's' : ''
33
const srv = goSecure ? https : (http?.listening && http)
34
const href = srv && `http${goSecure}://`+window.location.hostname + (srv.port === (goSecure ? 443 : 80) ? '' : ':'+srv.port)
33
- const errorMap = objSameKeys(status, v =>
35
+ const serverStatus = _.pick(status, ['http', 'https'])
36
+ const serverErrors = objSameKeys(serverStatus, v =>
37
v.busy ? [`port ${v.port} already used by ${v.busy}${SOLUTION_SEP}choose a `, cfgLink('different port'), ` or stop ${v.busy}`]
38
: v.error )
36
- const errors = errorMap && onlyTruthy(Object.entries(errorMap).map(([k,v]) =>
39
+ const errors = serverErrors && onlyTruthy(Object.entries(serverErrors).map(([k,v]) =>
40
v && [md(`Protocol _${k}_ cannot work: `), v,
41
(isCertError(v) || isKeyError(v)) && [
42
SOLUTION_SEP, h(Link, { sx: { cursor: 'pointer' }, onClick() { makeCertAndSave().then(reloadCfg).then(reloadStatus) } }, "make one"),
@@ -48,7 +51,7 @@ export default function HomePage() {
51
: entry('', md("This is Admin-panel, where you manage your server. Access your files on "),
52
h(Link, { target:'frontend', href: '/' }, "Front-end", h(Launch, { sx: { verticalAlign: 'sub', ml: '.2em' } }))),
53
!href && entry('warning', "Frontend unreachable: ",
51
- ['http','https'].map(k => k + " " + (errorMap[k] ? "is in error" : "is off")).join(', '),
54
+ _.map(serverErrors, (v,k) => k + " " + (v ? "is in error" : "is off")).join(', '),
55
!errors.length && [ SOLUTION_SEP, cfgLink("switch http or https on") ]
56
),
57
plugins.find(x => x.badApi) && entry('warning', "Some plugins may be incompatible"),
shared/index.ts
+1
-1
@@ -52,7 +52,7 @@ export function getCookie(name: string) {
52
return ''
53
}
54
55
-export function objSameKeys<S extends object,VR=any>(src: S, newValue:(value:Truthy<S[keyof S]>, key:keyof S)=>any) {
55
+export function objSameKeys<S extends object,VR=any>(src: S, newValue:(value:Truthy<S[keyof S]>, key:keyof S)=>VR) {
56
return Object.fromEntries(Object.entries(src).map(([k,v]) => [k, newValue(v,k as keyof S)])) as { [K in keyof S]:VR }
57
}
58