admin/plugins: button-link to repo
Massimo Melina committed
May 12, 2022 at 23:18 UTC
dea5be1550f44655f37e9671879b56b0cd48a905
3 files changed
+43
-18
admin/src/InstalledPlugins.ts
+11
-2
@@ -2,7 +2,7 @@ import { apiCall, useApiList } from './api'
2
import { createElement as h, Fragment } from 'react'
3
import { Alert, Box, Tooltip } from '@mui/material'
4
import { DataGrid } from '@mui/x-data-grid'
5
-import { Delete, Error, PlayCircle, Settings, StopCircle, SystemUpdateAlt } from '@mui/icons-material'
5
+import { Delete, Error, GitHub, PlayCircle, Settings, StopCircle, SystemUpdateAlt } from '@mui/icons-material'
6
import { IconBtn } from './misc'
7
import { formDialog, toast } from './dialog'
8
import _ from 'lodash'
@@ -31,7 +31,8 @@ export default function InstalledPlugins({ updates }: { updates?: true }) {
31
renderCell({ row, value }) {
32
return h(Fragment, {},
33
value,
34
- typeof row.badApi === 'string' && h(Tooltip, { title: row.badApi, children: h(Error, { color: 'warning', sx: { ml: 1 } }) })
34
+ typeof row.badApi === 'string' && h(Tooltip, { title: row.badApi, children: h(Error, { color: 'warning', sx: { ml: 1 } }) }),
35
+ repoLink(row.repo),
36
)
37
}
38
},
@@ -134,3 +135,11 @@ const type2comp = {
135
multiselect: MultiSelectField,
136
array: ArrayField,
137
}
138
+
139
+export function repoLink(repo?: string) {
140
+ return repo && h(IconBtn, {
141
+ icon: GitHub,
142
+ title: "Open web page",
143
+ link: 'https://github.com/' + repo,
144
+ })
145
+}
admin/src/OnlinePlugins.ts
+18
-13
@@ -2,11 +2,12 @@ import { apiCall, useApiList } from './api'
2
import { Fragment, createElement as h, useState } from 'react'
3
import { Alert } from '@mui/material'
4
import { DataGrid } from '@mui/x-data-grid'
5
-import { IconBtn, spinner } from './misc'
6
-import { Download, Search } from '@mui/icons-material'
5
+import { IconBtn } from './misc'
6
+import { Download, GitHub, Search } from '@mui/icons-material'
7
import { confirmDialog, toast } from './dialog'
8
import { StringField } from './Form'
9
import { useDebounce } from 'use-debounce'
10
+import { repoLink } from './InstalledPlugins'
11
12
export default function OnlinePlugins() {
13
const [search, setSearch] = useState('')
@@ -47,17 +48,21 @@ export default function OnlinePlugins() {
48
hideSortIcons: true,
49
disableColumnMenu: true,
50
renderCell({ row }) {
50
- return row.downloading ? spinner() : h(IconBtn, {
51
- icon: Download,
52
- title: "Download",
53
- disabled: row.installed && "Already installed",
54
- async onClick() {
55
- if (!await confirmDialog("WARNING - Proceed only if you trust this author and this plugin")) return
56
- const { id } = row
57
- return apiCall('download_plugin', { id })
58
- .then(() => toast("Plugin downloaded: " + id))
59
- }
60
- })
51
+ const { id } = row
52
+ return h('div', {},
53
+ repoLink(id),
54
+ h(IconBtn, {
55
+ icon: Download,
56
+ title: "Download",
57
+ progress: row.downloading,
58
+ disabled: row.installed && "Already installed",
59
+ async onClick() {
60
+ if (!await confirmDialog("WARNING - Proceed only if you trust this author and this plugin")) return
61
+ return apiCall('download_plugin', { id })
62
+ .then(() => toast("Plugin downloaded: " + id))
63
+ }
64
+ })
65
+ )
66
}
67
},
68
]
admin/src/misc.ts
+14
-3
@@ -28,13 +28,15 @@ export function modifiedSx(is: boolean) {
28
return is ? { outline: '2px solid' } : undefined
29
}
30
31
-interface IconBtnProps { title?: string, icon: SvgIconComponent, disabled?: boolean | string, [rest:string]:any }
32
-export function IconBtn({ title, icon, onClick, disabled, ...rest }: IconBtnProps) {
31
+interface IconBtnProps { title?: string, icon: SvgIconComponent, disabled?: boolean | string, progress?: boolean | number, link?: string, [rest:string]:any }
32
+export function IconBtn({ title, icon, onClick, disabled, progress=false, link, ...rest }: IconBtnProps) {
33
const [loading, setLoading] = useStateMounted(false)
34
if (typeof disabled === 'string')
35
title = disabled
36
+ if (link)
37
+ onClick = () => window.open(link)
38
let ret: ReturnType<FC> = h(IconButton, {
37
- disabled: loading || Boolean(disabled),
39
+ disabled: loading || progress !== false || Boolean(disabled),
40
...rest,
41
onClick() {
42
const ret = onClick?.apply(this,arguments)
@@ -44,6 +46,15 @@ export function IconBtn({ title, icon, onClick, disabled, ...rest }: IconBtnProp
46
}
47
}
48
}, h(icon))
49
+ if (progress || loading)
50
+ ret = h(Box, { position:'relative' },
51
+ h(CircularProgress, {
52
+ ...(typeof progress === 'number' ? { value: progress, variant: 'determinate' } : null),
53
+ size: 48,
54
+ style: { position:'absolute' }
55
+ }),
56
+ ret
57
+ )
58
if (title)
59
ret = h(Tooltip, { title, children: h('span',{},ret) })
60
return ret