Refactor Link Handling in Dashboard Components

- Introduced ExternalLink component to manage external links consistently across the application, enhancing user experience in Electron environments.
- Updated About and UrlDisplay components to utilize ExternalLink for improved link handling and to ensure proper behavior in Electron.
- Removed direct usage of Ant Design's Link component in favor of the new ExternalLink, streamlining the codebase and enhancing maintainability.
This commit is contained in:
Tom Butcher 2026-08-23 22:33:36 +01:00
parent 4f6b7e253b
commit c0609cb097
3 changed files with 51 additions and 9 deletions

View File

@ -21,7 +21,8 @@ import { AppUpdateContext } from '../context/AppUpdateContext'
import { useMediaQuery } from 'react-responsive'
import FarmControlAppIcon from '../../Logos/FarmControlAppIcon'
import SoftwareUpdateIcon from '../../Icons/SoftwareUpdateIcon'
const { Title, Text, Link } = Typography
import ExternalLink from '../common/ExternalLink'
const { Title, Text } = Typography
const About = () => {
const [collapseState, updateCollapseState] = useCollapseState('About', {
@ -171,11 +172,13 @@ const About = () => {
Development
</Tag>
)}
<Link href='https://ci.tombutcher.work/job/farmcontrol'>
<ExternalLink href='https://ci.tombutcher.work/job/farmcontrol'>
Jenkins
</Link>
</ExternalLink>
<Divider type='vertical' style={{ margin: 0 }} />
<Link href='https://github.com/farmcontrol'>GitHub</Link>
<ExternalLink href='https://git.tombutcher.work/farmcontrol'>
Git
</ExternalLink>
</Flex>
</Flex>
</Flex>

View File

@ -0,0 +1,40 @@
import { useContext } from 'react'
import PropTypes from 'prop-types'
import { Typography } from 'antd'
import { ElectronContext } from '../context/ElectronContext'
const { Link } = Typography
const ExternalLink = ({ href, children, onClick, ...props }) => {
const { isElectron, openExternalUrl } = useContext(ElectronContext)
const handleClick = (event) => {
onClick?.(event)
if (event.defaultPrevented) return
if (isElectron) {
event.preventDefault()
openExternalUrl(href)
}
}
return (
<Link
{...props}
href={href}
target={isElectron ? undefined : '_blank'}
rel={isElectron ? undefined : 'noopener noreferrer'}
onClick={handleClick}
>
{children}
</Link>
)
}
ExternalLink.propTypes = {
href: PropTypes.string.isRequired,
children: PropTypes.node,
onClick: PropTypes.func
}
export default ExternalLink

View File

@ -4,8 +4,9 @@ import Tooltip from './Tooltip'
import LinkIcon from '../../Icons/LinkIcon'
import CopyButton from './CopyButton'
import ElipsisText from './ElipsisText'
import ExternalLink from './ExternalLink'
const { Text, Link } = Typography
const { Text } = Typography
const UrlDisplay = ({ url, showCopy = true, showLink = false }) => {
if (!url) return <Text type='secondary'>n/a</Text>
@ -14,10 +15,8 @@ const UrlDisplay = ({ url, showCopy = true, showLink = false }) => {
<>
<Flex style={{ minWidth: 0 }}>
{showLink ? (
<Link
<ExternalLink
href={url}
target='_blank'
rel='noopener noreferrer'
style={{
marginRight: 8,
minWidth: 0,
@ -29,7 +28,7 @@ const UrlDisplay = ({ url, showCopy = true, showLink = false }) => {
<ElipsisText style={{ display: 'block' }}>
{url}
</ElipsisText>
</Link>
</ExternalLink>
) : (
<>
<ElipsisText style={{ marginRight: 8, minWidth: 0 }}>