a way into the plugin from its detail panel
installing something and then having to guess its url is a small thing that makes the whole flow feel unfinished. the detail panel now links to the plugin's screen. shown only while installed AND enabled, and only when the plugin has a frontend at all. a link to an unmounted route lands on the home page, because the shell redirects an unknown path — which reads as a broken link rather than a plugin that is switched off. a backend-only plugin has no screen to open and gets no link rather than a dead one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useSearchParams } from 'react-router';
|
||||
import { Link, useSearchParams } from 'react-router';
|
||||
import { usePlugins, type PluginItem } from './usePlugins';
|
||||
|
||||
// The right panel: one plugin, and the four verbs.
|
||||
@@ -105,6 +105,21 @@ export const PluginDetail = () => {
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
{/* The way in, when there is one.
|
||||
Only while installed AND enabled: a link to a route that is not mounted is a link to the home
|
||||
page, since the shell redirects an unknown path — which reads as the link being broken rather
|
||||
than the plugin being off. `has.web` because a plugin can be entirely backend and have no screen
|
||||
to open at all. */}
|
||||
{plugin.installed && plugin.enabled && plugin.has.web ? (
|
||||
<Link
|
||||
to={plugin.prefix}
|
||||
className="mt-6 inline-flex items-center gap-1.5 text-sm text-duck-teal hover:underline"
|
||||
>
|
||||
Open {plugin.label}
|
||||
<span aria-hidden>→</span>
|
||||
</Link>
|
||||
) : null}
|
||||
|
||||
<div className="mt-6 flex flex-wrap gap-2">
|
||||
{!plugin.installed ? (
|
||||
<Button tone="primary" disabled={busy} onClick={() => run('install', plugin.appName)}>
|
||||
|
||||
Reference in New Issue
Block a user