diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json
index de45ea618..5bcf94240 100644
--- a/webapp/i18n/en.json
+++ b/webapp/i18n/en.json
@@ -16,6 +16,8 @@
"CardDetail.new-comment-placeholder": "Add a comment...",
"CardDialog.editing-template": "You're editing a template.",
"CardDialog.nocard": "This card doesn't exist or is inaccessible.",
+ "CardDialog.copiedLink": "Copied!",
+ "CardDialog.copyLink": "Copy link",
"ColorOption.selectColor": "Select {color} Color",
"Comment.delete": "Delete",
"CommentsList.send": "Send",
@@ -51,11 +53,15 @@
"FilterComponent.delete": "Delete",
"GalleryCard.delete": "Delete",
"GalleryCard.duplicate": "Duplicate",
+ "GalleryCard.copiedLink": "Copied!",
+ "GalleryCard.copyLink": "Copy link",
"GroupBy.ungroup": "Ungroup",
"General.BoardCount": "{count, plural, one {# Board} other {# Boards}}",
"KanbanCard.delete": "Delete",
"KanbanCard.duplicate": "Duplicate",
"KanbanCard.untitled": "Untitled",
+ "KanbanCard.copiedLink": "Copied!",
+ "KanbanCard.copyLink": "Copy link",
"Mutator.duplicate-board": "duplicate board",
"Mutator.new-board-from-template": "new board from template",
"Mutator.new-card-from-template": "new card from template",
diff --git a/webapp/src/components/cardDialog.tsx b/webapp/src/components/cardDialog.tsx
index 1ecf4c748..b32602368 100644
--- a/webapp/src/components/cardDialog.tsx
+++ b/webapp/src/components/cardDialog.tsx
@@ -9,6 +9,7 @@ import {BoardView} from '../blocks/boardView'
import {Board} from '../blocks/board'
import {Card} from '../blocks/card'
import DeleteIcon from '../widgets/icons/delete'
+import LinkIcon from '../widgets/icons/Link'
import Menu from '../widgets/menu'
import {useAppSelector} from '../store/hooks'
@@ -18,6 +19,7 @@ import {getCardComments} from '../store/comments'
import CardDetail from './cardDetail/cardDetail'
import Dialog from './dialog'
+import {sendFlashMessage} from './flashMessages'
type Props = {
board: Board
@@ -71,6 +73,21 @@ const CardDialog = (props: Props) => {
props.onClose()
}}
/>
+
}
+ id='copy'
+ name={intl.formatMessage({id: 'CardDialog.copyLink', defaultMessage: 'Copy link'})}
+ onClick={() => {
+ let cardLink = window.location.href
+
+ if (!cardLink.includes(props.cardId)) {
+ cardLink += `/${props.cardId}`
+ }
+
+ Utils.copyTextToClipboard(cardLink)
+ sendFlashMessage({content: intl.formatMessage({id: 'CardDialog.copiedLink', defaultMessage: 'Copied!'}), severity: 'high'})
+ }}
+ />
{(card && !card.fields.isTemplate) &&
{
mutator.duplicateCard(card.id)
}}
/>
+ }
+ id='copy'
+ name={intl.formatMessage({id: 'GalleryCard.copyLink', defaultMessage: 'Copy link'})}
+ onClick={() => {
+ let cardLink = window.location.href
+
+ if (!cardLink.includes(card.id)) {
+ cardLink += `/${card.id}`
+ }
+
+ Utils.copyTextToClipboard(cardLink)
+ sendFlashMessage({content: intl.formatMessage({id: 'GalleryCard.copiedLink', defaultMessage: 'Copied!'}), severity: 'high'})
+ }}
+ />
}
diff --git a/webapp/src/components/kanban/kanbanCard.tsx b/webapp/src/components/kanban/kanbanCard.tsx
index 916af303e..ea0baaceb 100644
--- a/webapp/src/components/kanban/kanbanCard.tsx
+++ b/webapp/src/components/kanban/kanbanCard.tsx
@@ -10,9 +10,12 @@ import IconButton from '../../widgets/buttons/iconButton'
import DeleteIcon from '../../widgets/icons/delete'
import DuplicateIcon from '../../widgets/icons/duplicate'
import OptionsIcon from '../../widgets/icons/options'
+import LinkIcon from '../../widgets/icons/Link'
import Menu from '../../widgets/menu'
import MenuWrapper from '../../widgets/menuWrapper'
import {useSortable} from '../../hooks/sortable'
+import {Utils} from '../../utils'
+import {sendFlashMessage} from '../flashMessages'
import {useAppSelector} from '../../store/hooks'
import {getCardContents} from '../../store/contents'
import {getCardComments} from '../../store/comments'
@@ -85,6 +88,21 @@ const KanbanCard = React.memo((props: Props) => {
)
}}
/>
+ }
+ id='copy'
+ name={intl.formatMessage({id: 'KanbanCard.copyLink', defaultMessage: 'Copy link'})}
+ onClick={() => {
+ let cardLink = window.location.href
+
+ if (!cardLink.includes(card.id)) {
+ cardLink += `/${card.id}`
+ }
+
+ Utils.copyTextToClipboard(cardLink)
+ sendFlashMessage({content: intl.formatMessage({id: 'KanbanCard.copiedLink', defaultMessage: 'Copied!'}), severity: 'high'})
+ }}
+ />
}
diff --git a/webapp/src/widgets/icons/Link.tsx b/webapp/src/widgets/icons/Link.tsx
index c8d98525c..b074e0638 100644
--- a/webapp/src/widgets/icons/Link.tsx
+++ b/webapp/src/widgets/icons/Link.tsx
@@ -5,6 +5,8 @@ import React from 'react'
import CompassIcon from './compassIcon'
+import './link.scss'
+
export default function LinkIcon(): JSX.Element {
return (