diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index 5df66e77b..35e886601 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -338,6 +338,9 @@ "name": "Name", "description": "Description", "version": "Version", + "author": "Author", + "website": "Website", + "permissions": "Permissions", "enabled": "Enabled", "status": "Status", "path": "Path", diff --git a/ui/src/plugin/PluginShow.jsx b/ui/src/plugin/PluginShow.jsx index f683aab60..30c90aa06 100644 --- a/ui/src/plugin/PluginShow.jsx +++ b/ui/src/plugin/PluginShow.jsx @@ -22,9 +22,12 @@ import { Accordion, AccordionSummary, AccordionDetails, + Chip, + Tooltip, + Link, } from '@material-ui/core' import { makeStyles } from '@material-ui/core/styles' -import { MdExpandMore, MdError, MdCheckCircle } from 'react-icons/md' +import { MdExpandMore, MdError } from 'react-icons/md' import { Title, DateField } from '../common' import { validateJson } from './jsonValidation' @@ -71,15 +74,6 @@ const useStyles = makeStyles((theme) => ({ fontFamily: 'monospace', fontSize: '0.85rem', }, - statusEnabled: { - color: theme.palette.success?.main || theme.palette.primary.main, - display: 'flex', - alignItems: 'center', - gap: theme.spacing(0.5), - }, - statusDisabled: { - color: theme.palette.text.secondary, - }, toolbar: { display: 'flex', justifyContent: 'flex-start', @@ -104,8 +98,63 @@ const useStyles = makeStyles((theme) => ({ fontSize: '0.85rem', wordBreak: 'break-all', }, + permissionsContainer: { + display: 'flex', + flexWrap: 'wrap', + gap: theme.spacing(0.5), + }, + permissionChip: { + fontSize: '0.75rem', + }, + tooltipContent: { + '& code': { + fontFamily: 'monospace', + fontSize: '0.8em', + backgroundColor: 'rgba(255,255,255,0.1)', + padding: '1px 4px', + borderRadius: 2, + }, + }, })) +const PermissionChip = ({ label, permission }) => { + const classes = useStyles() + + if (!permission) return null + + const hasHosts = permission.allowedHosts?.length > 0 + const tooltipContent = ( + + {permission.reason && {permission.reason}} + {hasHosts && ( + + + Allowed hosts: {permission.allowedHosts.map((host, i) => ( + {i > 0 && ', '}{host} + ))} + + + )} + + ) + + const hasTooltip = permission.reason || hasHosts + + const chip = ( + + ) + + return hasTooltip ? ( + + {chip} + + ) : chip +} + const PluginTitle = ({ record }) => { const translate = useTranslate() const resourceName = translate('resources.plugin.name', { smart_count: 1 }) @@ -202,46 +251,27 @@ const PluginShowContent = () => { )} - {/* Status and Enable/Disable */} + {/* Status - Enable/Disable Switch Only */} {translate('resources.plugin.sections.status')} - - - {record.enabled ? ( - - - {translate('resources.plugin.status.enabled')} - - ) : ( - - {translate('resources.plugin.status.disabled')} - - )} - - - } - label={translate( - record.enabled - ? 'resources.plugin.actions.disable' - : 'resources.plugin.actions.enable', - )} - labelPlacement="start" - /> - + + } + label={translate( + record.enabled + ? 'resources.plugin.actions.disable' + : 'resources.plugin.actions.enable', + )} + /> @@ -252,9 +282,16 @@ const PluginShowContent = () => { {translate('resources.plugin.sections.info')}
-
{translate('resources.plugin.fields.name')}
+
{translate('resources.plugin.fields.id')}
{record.id}
+ {manifest?.name && ( + <> +
{translate('resources.plugin.fields.name')}
+
{manifest.name}
+ + )} + {manifest?.version && ( <>
{translate('resources.plugin.fields.version')}
@@ -269,6 +306,42 @@ const PluginShowContent = () => { )} + {manifest?.author && ( + <> +
{translate('resources.plugin.fields.author')}
+
{manifest.author}
+ + )} + + {manifest?.website && ( + <> +
{translate('resources.plugin.fields.website')}
+
+ + {manifest.website} + +
+ + )} + + {manifest?.permissions && ( + <> +
{translate('resources.plugin.fields.permissions')}
+
+ + + + + + +
+ + )} +
{translate('resources.plugin.fields.path')}
{record.path}
@@ -285,6 +358,20 @@ const PluginShowContent = () => { + {/* Manifest (Collapsible) */} + + }> + + {translate('resources.plugin.sections.manifest')} + + + + + {manifestJson} + + + + {/* Configuration */} @@ -318,20 +405,6 @@ const PluginShowContent = () => { - - {/* Manifest */} - - }> - - {translate('resources.plugin.sections.manifest')} - - - - - {manifestJson} - - - ) }