2025-05-10 02:09:06 +02:00
|
|
|
/*!
|
|
|
|
* Copyright (c) 2024 PLANKA Software GmbH
|
|
|
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
|
|
|
*/
|
|
|
|
|
2025-07-08 17:15:48 +02:00
|
|
|
import React, { useCallback, useMemo } from 'react';
|
2024-04-10 15:53:05 +02:00
|
|
|
import PropTypes from 'prop-types';
|
2025-07-08 17:15:48 +02:00
|
|
|
import { useSelector } from 'react-redux';
|
2024-04-10 15:53:05 +02:00
|
|
|
|
2025-07-11 01:04:02 +02:00
|
|
|
import history from '../../../history';
|
|
|
|
import selectors from '../../../selectors';
|
|
|
|
import matchPaths from '../../../utils/match-paths';
|
|
|
|
import Paths from '../../../constants/Paths';
|
2024-04-10 15:53:05 +02:00
|
|
|
|
2025-07-11 01:04:02 +02:00
|
|
|
const Linkify = React.memo(({ href, content, stopPropagation, ...props }) => {
|
2025-07-08 17:15:48 +02:00
|
|
|
const selectCardById = useMemo(() => selectors.makeSelectCardById(), []);
|
|
|
|
|
|
|
|
const url = useMemo(() => {
|
|
|
|
try {
|
2025-07-11 01:04:02 +02:00
|
|
|
return new URL(href, window.location);
|
2025-07-08 17:15:48 +02:00
|
|
|
} catch {
|
|
|
|
return null;
|
|
|
|
}
|
2025-07-11 01:04:02 +02:00
|
|
|
}, [href]);
|
2025-07-08 17:15:48 +02:00
|
|
|
|
|
|
|
const isSameSite = !!url && url.origin === window.location.origin;
|
|
|
|
|
|
|
|
const cardsPathMatch = useMemo(() => {
|
|
|
|
if (!isSameSite) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return matchPaths(url.pathname, [Paths.CARDS]);
|
|
|
|
}, [url.pathname, isSameSite]);
|
|
|
|
|
|
|
|
const card = useSelector((state) => {
|
|
|
|
if (!cardsPathMatch) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return selectCardById(state, cardsPathMatch.params.id);
|
|
|
|
});
|
|
|
|
|
2025-07-11 01:04:02 +02:00
|
|
|
const handleClick = useCallback(
|
2024-04-10 15:53:05 +02:00
|
|
|
(event) => {
|
2025-07-11 01:04:02 +02:00
|
|
|
if (stopPropagation) {
|
2024-04-10 15:53:05 +02:00
|
|
|
event.stopPropagation();
|
|
|
|
}
|
|
|
|
|
2025-07-08 17:15:48 +02:00
|
|
|
if (isSameSite) {
|
2024-04-10 15:53:05 +02:00
|
|
|
event.preventDefault();
|
|
|
|
history.push(event.target.href);
|
|
|
|
}
|
|
|
|
},
|
2025-07-11 01:04:02 +02:00
|
|
|
[stopPropagation, isSameSite],
|
2024-04-10 15:53:05 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
2025-07-11 01:04:02 +02:00
|
|
|
<a
|
2024-04-10 15:53:05 +02:00
|
|
|
{...props} // eslint-disable-line react/jsx-props-no-spreading
|
2025-07-11 01:04:02 +02:00
|
|
|
href={href}
|
|
|
|
target={isSameSite ? undefined : '_blank'}
|
|
|
|
rel={isSameSite ? undefined : 'noreferrer'}
|
|
|
|
onClick={handleClick}
|
2024-04-10 15:53:05 +02:00
|
|
|
>
|
2025-07-11 01:04:02 +02:00
|
|
|
{card ? card.name : content}
|
|
|
|
</a>
|
2024-04-10 15:53:05 +02:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
Linkify.propTypes = {
|
2025-07-11 01:04:02 +02:00
|
|
|
href: PropTypes.string.isRequired,
|
|
|
|
content: PropTypes.string.isRequired,
|
|
|
|
stopPropagation: PropTypes.bool,
|
2024-04-10 15:53:05 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Linkify.defaultProps = {
|
2025-07-11 01:04:02 +02:00
|
|
|
stopPropagation: false,
|
2024-04-10 15:53:05 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
export default Linkify;
|