admin/plugin/online: offer to start plugin after installation
Massimo Melina committed
Aug 7, 2022 at 17:13 UTC
03643b0681be507a37677f8949efe4a54bcedd0a
5 files changed
+28
-19
admin/src/InstalledPlugins.ts
+6
-3
@@ -67,9 +67,7 @@ export default function InstalledPlugins({ updates }: { updates?: true }) {
67
} : {
68
icon: PlayCircle,
69
title: `Start ${id}`,
70
- onClick: () =>
71
- apiCall('set_plugin', { id, enabled: true }).then(() =>
72
- toast("Plugin is starting", h(PlayCircle, { color: 'success' }))),
70
+ onClick: () => startPlugin(id),
71
}),
72
h(IconBtn, {
73
icon: Settings,
@@ -153,3 +151,8 @@ export function UpdateButton({ id, then }: { id: string, then: (id:string)=>void
151
}
152
})
153
}
154
+
155
+export function startPlugin(id: string) {
156
+ return apiCall('set_plugin', { id, enabled: true }).then(() =>
157
+ toast("Plugin is starting", h(PlayCircle, { color: 'success' })))
158
+}
admin/src/OnlinePlugins.ts
+7
-5
@@ -3,12 +3,13 @@ import { Fragment, createElement as h, useState } from 'react'
3
import { DataGrid } from '@mui/x-data-grid'
4
import { IconBtn } from './misc'
5
import { Download, Search } from '@mui/icons-material'
6
-import { toast } from './dialog'
6
+import { confirmDialog } from './dialog'
7
import { StringField } from '@hfs/mui-grid-form'
8
import { useDebounce } from 'use-debounce'
9
-import { repoLink, showError, UpdateButton } from './InstalledPlugins'
9
+import { repoLink, showError, startPlugin, UpdateButton } from './InstalledPlugins'
10
import { state, useSnapState } from './state'
11
import _ from 'lodash'
12
+import md from './md'
13
14
export default function OnlinePlugins() {
15
const [search, setSearch] = useState('')
@@ -79,14 +80,15 @@ export default function OnlinePlugins() {
80
}
81
}) : h(IconBtn, {
82
icon: Download,
82
- title: "Download",
83
+ title: "Install",
84
progress: row.downloading,
85
disabled: row.installed && "Already installed",
86
tooltipProps: { placement:'bottom-end' }, // workaround problem with horizontal scrolling by moving the tooltip leftward
87
confirm: "WARNING - Proceed only if you trust this author and this plugin",
88
async onClick() {
88
- await apiCall('download_plugin', { id, branch })
89
- toast("Plugin downloaded: " + id)
89
+ const { id: installedId } = await apiCall('download_plugin', { id, branch })
90
+ if (await confirmDialog(md(`Plugin /${id}/ installed.\nDo you want to start it now?`)))
91
+ await startPlugin(installedId)
92
}
93
})
94
)
admin/src/dialog.ts
+11
-8
@@ -79,7 +79,8 @@ export async function alertDialog(msg: ReactElement | string | Error, options?:
79
sx: { position: 'absolute', right: 0, top: 0, opacity: .5 }
80
}, h(Close)),
81
opt.icon ?? h(type2ico[type], { color: type, fontSize: 'large' }),
82
- isValidElement(msg) ? msg : h(Box, { fontSize: 'large', mb: 1 }, String(msg)),
82
+ isValidElement(msg) ? msg
83
+ : h(Box, { fontSize: 'large', mb: 1, lineHeight: '1.8em' }, String(msg)),
84
)
85
}
86
})
@@ -87,7 +88,7 @@ export async function alertDialog(msg: ReactElement | string | Error, options?:
88
}
89
90
interface ConfirmOptions { href?: string }
90
-export async function confirmDialog(msg: string, { href }: ConfirmOptions={}) : Promise<boolean> {
91
+export async function confirmDialog(msg: string | ReactElement, { href }: ConfirmOptions={}) : Promise<boolean> {
92
return new Promise(resolve => newDialog({
93
className: 'dialog-confirm',
94
icon: '?',
@@ -96,12 +97,14 @@ export async function confirmDialog(msg: string, { href }: ConfirmOptions={}) :
97
}) )
98
99
function Content() {
99
- return h('div', {},
100
- h('p', {}, msg),
101
- h('a', {
102
- href,
103
- onClick: () => closeDialog(true),
104
- }, h(Button, {}, 'Confirm'))
100
+ return h(Fragment, {},
101
+ h(Box, { mb: 2 }, msg),
102
+ h(Box, { textAlign: 'right' },
103
+ h('a', {
104
+ href,
105
+ onClick: () => closeDialog(true),
106
+ }, h(Button, {}, 'Confirm'))
107
+ ),
108
)
109
}
110
}
server/src/api.plugins.ts
+2
-2
@@ -116,8 +116,8 @@ const apis: ApiHandlers = {
116
},
117
118
async download_plugin(pl) {
119
- await downloadPlugin(pl.id, pl.branch)
120
- return {}
119
+ const res = await downloadPlugin(pl.id, pl.branch)
120
+ return typeof res === 'string' ? getPluginInfo(res) : res
121
},
122
123
async update_plugin(pl) {
server/src/github.ts
+2
-1
@@ -28,7 +28,7 @@ export async function downloadPlugin(repo: string, branch='', overwrite?: boolea
28
branch = rec.default_branch
29
const short = repo.split('/')[1] // second part, repo without the owner
30
const folder2repo = getFolder2repo()
31
- const folder = overwrite ? _.findKey(folder2repo, x => x===repo) // use existing folder
31
+ const folder = overwrite ? _.findKey(folder2repo, x => x===repo)! // use existing folder
32
: short in folder2repo ? repo.replace('/','-') // longer form only if another plugin is using short form
33
: short
34
const installPath = PLUGINS_PATH + '/' + folder
@@ -39,6 +39,7 @@ export async function downloadPlugin(repo: string, branch='', overwrite?: boolea
39
path.startsWith(rootWithinZip) && installPath + '/' + path.slice(rootWithinZip.length) )
40
downloadProgress(repo, undefined)
41
await rescan() // workaround: for some reason, operations are not triggering the rescan of the watched folder. Let's invoke it.
42
+ return folder
43
}
44
45
export function getRepoInfo(id: string) {