import { css } from '@emotion/css';
import { useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { reportInteraction } from '@grafana/runtime';
import { PageInfoItem } from '@grafana/runtime/src/components/PluginPage';
import {
Stack,
Text,
LinkButton,
Box,
TextLink,
CollapsableSection,
Tooltip,
Icon,
Modal,
Button,
useStyles2,
} from '@grafana/ui';
import { Trans } from 'app/core/internationalization';
import { formatDate } from 'app/core/internationalization/dates';
import { CatalogPlugin } from '../types';
type Props = {
pluginExtentionsInfo: PageInfoItem[];
plugin: CatalogPlugin;
width?: string;
};
export function PluginDetailsPanel(props: Props): React.ReactElement | null {
const { pluginExtentionsInfo, plugin, width = '250px' } = props;
const [reportAbuseModalOpen, setReportAbuseModalOpen] = useState(false);
const normalizeURL = (url: string | undefined) => url?.replace(/\/$/, '');
const customLinks = plugin.details?.links?.filter((link) => {
const customLinksFiltered = ![plugin.url, plugin.details?.licenseUrl, plugin.details?.documentationUrl]
.map(normalizeURL)
.includes(normalizeURL(link.url));
return customLinksFiltered;
});
const shouldRenderLinks = plugin.url || plugin.details?.licenseUrl || plugin.details?.documentationUrl;
const styles = useStyles2(getStyles);
const onClickReportConcern = (pluginId: string) => {
setReportAbuseModalOpen(true);
reportInteraction('plugin_detail_report_concern', {
plugin_id: pluginId,
});
};
return (
<>
{pluginExtentionsInfo.map((infoItem, index) => {
return (
{infoItem.label + ':'}
{infoItem.value}
);
})}
{plugin.updatedAt && (
Last updated:
{' '}
{formatDate(new Date(plugin.updatedAt), { day: 'numeric', month: 'short', year: 'numeric' })}
)}
{plugin?.details?.lastCommitDate && (
Last commit date:
{' '}
{formatDate(new Date(plugin.details.lastCommitDate), {
day: 'numeric',
month: 'short',
year: 'numeric',
})}
)}
{shouldRenderLinks && (
<>
{plugin.url && (
Repository
)}
{plugin.raiseAnIssueUrl && (
Raise an issue
)}
{plugin.details?.licenseUrl && (
License
)}
{plugin.details?.documentationUrl && (
Documentation
)}
>
)}
{customLinks && customLinks?.length > 0 && (
Custom links
These links are provided by the plugin developer to offer additional, developer-specific
resources and information
}
placement="right-end"
>
}
>
{customLinks.map((link, index) => (
{link.name}
))}
)}
{!plugin?.isCore && (
Report a concern
Report issues related to malicious or harmful plugins directly to Grafana Labs.
}
placement="right-end"
>
}
>
)}
{reportAbuseModalOpen && (
Report a plugin concern}
isOpen
onDismiss={() => setReportAbuseModalOpen(false)}
>
This feature is for reporting malicious or harmful behaviour within plugins. For plugin concerns, email
us at:{' '}
integrations@grafana.com
Note: For general plugin issues like bugs or feature requests, please contact the plugin author using
the provided links.{' '}
)}
>
);
}
export const getStyles = (theme: GrafanaTheme2) => {
return {
pluginVersionDetails: css({
wordBreak: 'break-word',
}),
};
};