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', }), }; };