Skip to content

Commit

Permalink
feat: Display clickable links in tasks (#694)
Browse files Browse the repository at this point in the history
Closes #330
  • Loading branch information
HannesOberreiter committed Apr 10, 2024
1 parent ea1b3b7 commit cc32daa
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 2 deletions.
16 changes: 16 additions & 0 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions client/package.json
Expand Up @@ -70,6 +70,8 @@
"initials": "^3.1.2",
"js-cookie": "^3.0.5",
"jwt-decode": "^4.0.0",
"linkify-react": "^4.1.3",
"linkifyjs": "^4.1.3",
"lodash": "^4.17.21",
"nanoid": "^5.0.3",
"node-sass": "^9.0.0",
Expand Down
4 changes: 3 additions & 1 deletion client/src/components/Card/Tasks.jsx
Expand Up @@ -4,6 +4,8 @@ import classNames from 'classnames';
import { Progress } from 'semantic-ui-react';
import { useToggle } from '../../lib/hooks';

import Linkify from '../Linkify';

import styles from './Tasks.module.scss';

const Tasks = React.memo(({ items }) => {
Expand Down Expand Up @@ -48,7 +50,7 @@ const Tasks = React.memo(({ items }) => {
key={item.id}
className={classNames(styles.task, item.isCompleted && styles.taskCompleted)}
>
{item.name}
<Linkify linkStopPropagation>{item.name}</Linkify>
</li>
))}
</ul>
Expand Down
2 changes: 2 additions & 0 deletions client/src/components/Card/Tasks.module.scss
Expand Up @@ -55,8 +55,10 @@
display: block;
font-size: 12px;
line-height: 14px;
overflow: hidden;
padding-bottom: 6px;
padding-left: 14px;
text-overflow: ellipsis;

&:before {
content: "";
Expand Down
3 changes: 2 additions & 1 deletion client/src/components/CardModal/Tasks/Item.jsx
Expand Up @@ -8,6 +8,7 @@ import { usePopup } from '../../../lib/popup';

import NameEdit from './NameEdit';
import ActionsStep from './ActionsStep';
import Linkify from '../../Linkify';

import styles from './Item.module.scss';

Expand Down Expand Up @@ -65,7 +66,7 @@ const Item = React.memo(
onClick={handleClick}
>
<span className={classNames(styles.task, isCompleted && styles.taskCompleted)}>
{name}
<Linkify linkStopPropagation>{name}</Linkify>
</span>
</span>
{isPersisted && canEdit && (
Expand Down
68 changes: 68 additions & 0 deletions client/src/components/Linkify.jsx
@@ -0,0 +1,68 @@
import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import LinkifyReact from 'linkify-react';

import history from '../history';

const Linkify = React.memo(({ children, linkStopPropagation, ...props }) => {
const handleLinkClick = useCallback(
(event) => {
if (linkStopPropagation) {
event.stopPropagation();
}

if (!event.target.getAttribute('target')) {
event.preventDefault();
history.push(event.target.href);
}
},
[linkStopPropagation],
);

const linkRenderer = useCallback(
({ attributes: { href, ...linkProps }, content }) => {
let url;
try {
url = new URL(href, window.location);
} catch (error) {} // eslint-disable-line no-empty

const isSameSite = !!url && url.origin === window.location.origin;

return (
<a
{...linkProps} // eslint-disable-line react/jsx-props-no-spreading
href={href}
target={isSameSite ? undefined : '_blank'}
rel={isSameSite ? undefined : 'noreferrer'}
onClick={handleLinkClick}
>
{isSameSite ? url.pathname : content}
</a>
);
},
[handleLinkClick],
);

return (
<LinkifyReact
{...props} // eslint-disable-line react/jsx-props-no-spreading
options={{
defaultProtocol: 'https',
render: linkRenderer,
}}
>
{children}
</LinkifyReact>
);
});

Linkify.propTypes = {
children: PropTypes.string.isRequired,
linkStopPropagation: PropTypes.bool,
};

Linkify.defaultProps = {
linkStopPropagation: false,
};

export default Linkify;

0 comments on commit cc32daa

Please sign in to comment.