mirror of
https://github.com/plankanban/planka.git
synced 2025-07-18 20:59:44 +02:00
feat: Add copy-to-clipboard for custom fields
This commit is contained in:
parent
99a06ce1ae
commit
3126a40bba
2 changed files with 68 additions and 10 deletions
|
@ -3,9 +3,10 @@
|
||||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { Button, Icon } from 'semantic-ui-react';
|
||||||
|
|
||||||
import selectors from '../../../selectors';
|
import selectors from '../../../selectors';
|
||||||
import entryActions from '../../../entry-actions';
|
import entryActions from '../../../entry-actions';
|
||||||
|
@ -48,6 +49,7 @@ const CustomField = React.memo(({ id, customFieldGroupId }) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const [isCopied, setIsCopied] = useState(false);
|
||||||
|
|
||||||
const handleValueUpdate = useCallback(
|
const handleValueUpdate = useCallback(
|
||||||
(content) => {
|
(content) => {
|
||||||
|
@ -64,18 +66,40 @@ const CustomField = React.memo(({ id, customFieldGroupId }) => {
|
||||||
[id, customFieldGroupId, cardId, dispatch],
|
[id, customFieldGroupId, cardId, dispatch],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleCopyClick = useCallback(() => {
|
||||||
|
if (isCopied) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
navigator.clipboard.writeText(customFieldValue.content);
|
||||||
|
|
||||||
|
setIsCopied(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsCopied(false);
|
||||||
|
}, 1000);
|
||||||
|
}, [customFieldValue, isCopied]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={styles.name}>{customField.name}</div>
|
<div className={styles.name}>{customField.name}</div>
|
||||||
{canEdit ? (
|
<div className={styles.valueWrapper}>
|
||||||
<ValueField
|
{canEdit ? (
|
||||||
defaultValue={customFieldValue && customFieldValue.content}
|
<ValueField
|
||||||
disabled={!customField.isPersisted}
|
defaultValue={customFieldValue && customFieldValue.content}
|
||||||
onUpdate={handleValueUpdate}
|
disabled={!customField.isPersisted}
|
||||||
/>
|
onUpdate={handleValueUpdate}
|
||||||
) : (
|
/>
|
||||||
<div className={styles.value}>{customFieldValue ? customFieldValue.content : '\u00A0'}</div>
|
) : (
|
||||||
)}
|
<div className={styles.value}>
|
||||||
|
{customFieldValue ? customFieldValue.content : '\u00A0'}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{customFieldValue && customFieldValue.content && (
|
||||||
|
<Button className={styles.copyButton} onClick={handleCopyClick}>
|
||||||
|
<Icon fitted name={isCopied ? 'check' : 'copy'} />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,30 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
:global(#app) {
|
:global(#app) {
|
||||||
|
.copyButton {
|
||||||
|
background: #ebeef0;
|
||||||
|
box-shadow: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-sizing: content-box;
|
||||||
|
color: #516b7a;
|
||||||
|
display: none;
|
||||||
|
height: 30px;
|
||||||
|
margin: 0;
|
||||||
|
min-height: auto;
|
||||||
|
outline: none;
|
||||||
|
padding: 4px;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
transition: background 85ms ease;
|
||||||
|
width: 20px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #dfe3e6;
|
||||||
|
color: #4c4c4c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
color: #6b808c;
|
color: #6b808c;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
@ -25,4 +49,14 @@
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.valueWrapper {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover:not(:has(input:focus)) {
|
||||||
|
.copyButton {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue