IconBtn.confirm

Massimo Melina committed May 13, 2022 at 01:11 UTC bca78fa2c57388360ba2cb16d82365532642b734
3 files changed +24 -14
admin/src/InstalledPlugins.ts
+1
@@ -97,6 +97,7 @@ export default function InstalledPlugins({ updates }: { updates?: true }) {
97 h(IconBtn, {
98 icon: Delete,
99 title: "Uninstall",
100 + confirm: "Remove?",
101 async onClick() {
102 await apiCall('uninstall_plugin', { id })
103 toast("Plugin uninstalled")
admin/src/OnlinePlugins.ts
+4 -4
@@ -4,7 +4,7 @@ import { Alert } from '@mui/material'
4 import { DataGrid } from '@mui/x-data-grid'
5 import { IconBtn } from './misc'
6 import { Download, Search } from '@mui/icons-material'
7 -import { confirmDialog, toast } from './dialog'
7 +import { toast } from './dialog'
8 import { StringField } from './Form'
9 import { useDebounce } from 'use-debounce'
10 import { repoLink } from './InstalledPlugins'
@@ -57,10 +57,10 @@ export default function OnlinePlugins() {
57 progress: row.downloading,
58 disabled: row.installed && "Already installed",
59 tooltipProps: { placement:'bottom-end' }, // workaround problem with horizontal scrolling by moving the tooltip leftward
60 + confirm: "WARNING - Proceed only if you trust this author and this plugin",
61 async onClick() {
61 - if (!await confirmDialog("WARNING - Proceed only if you trust this author and this plugin")) return
62 - return apiCall('download_plugin', { id })
63 - .then(() => toast("Plugin downloaded: " + id))
62 + await apiCall('download_plugin', { id })
63 + toast("Plugin downloaded: " + id)
64 }
65 })
66 )
admin/src/misc.ts
+19 -10
@@ -5,7 +5,7 @@ import { Box, CircularProgress, IconButton, Link, Tooltip } from '@mui/material'
5 import { Link as RouterLink } from 'react-router-dom'
6 import { SxProps } from '@mui/system'
7 import { SvgIconComponent } from '@mui/icons-material'
8 -import { alertDialog } from './dialog'
8 +import { alertDialog, confirmDialog } from './dialog'
9 import { apiCall } from './api'
10 import { onlyTruthy, useStateMounted } from '@hfs/shared'
11 export * from '@hfs/shared'
@@ -28,17 +28,27 @@ export function modifiedSx(is: boolean) {
28 return is ? { outline: '2px solid' } : undefined
29 }
30
31 -interface IconBtnProps { title?: ReactNode, icon: SvgIconComponent, disabled?: boolean | string, progress?: boolean | number, link?: string, [rest:string]:any }
32 -export function IconBtn({ title, icon, onClick, disabled, progress=false, link, tooltipProps, ...rest }: IconBtnProps) {
31 +interface IconBtnProps {
32 + title?: ReactNode
33 + icon: SvgIconComponent
34 + disabled?: boolean | string
35 + progress?: boolean | number
36 + link?: string
37 + confirm?: string
38 + [rest: string]: any
39 +}
40 +
41 +export function IconBtn({ title, icon, onClick, disabled, progress, link, tooltipProps, confirm, ...rest }: IconBtnProps) {
42 const [loading, setLoading] = useStateMounted(false)
43 if (typeof disabled === 'string')
44 title = disabled
45 if (link)
46 onClick = () => window.open(link)
47 let ret: ReturnType<FC> = h(IconButton, {
39 - disabled: loading || progress !== false || Boolean(disabled),
48 + disabled: Boolean(loading || progress || disabled),
49 ...rest,
41 - onClick() {
50 + async onClick() {
51 + if (confirm && !await confirmDialog(confirm)) return
52 const ret = onClick?.apply(this,arguments)
53 if (ret && ret instanceof Promise) {
54 setLoading(true)
@@ -46,12 +56,11 @@ export function IconBtn({ title, icon, onClick, disabled, progress=false, link,
56 }
57 }
58 }, h(icon))
49 - if (progress || loading)
50 - ret = h(Box, { position:'relative' },
59 + if ((progress || loading) && progress !== false) // false is also useful to inhibit behavior with loading
60 + ret = h(Box, { position:'relative', display: 'inline-block' },
61 h(CircularProgress, {
52 - ...(typeof progress === 'number' ? { value: progress, variant: 'determinate' } : null),
53 - size: 48,
54 - style: { position:'absolute' }
62 + ...(typeof progress === 'number' ? { value: progress*100, variant: 'determinate' } : null),
63 + style: { position:'absolute', top: 4, left: 4, width: 32, height: 32 }
64 }),
65 ret
66 )