mirror of
https://github.com/plankanban/planka.git
synced 2025-08-10 07:55:27 +02:00
added copy button to card modal
This commit is contained in:
parent
f06a99e581
commit
c61fcc36fa
5 changed files with 214 additions and 1 deletions
5
client/src/components/CardCopyPopup.jsx
Normal file
5
client/src/components/CardCopyPopup.jsx
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { withPopup } from '../lib/popup';
|
||||
|
||||
import CardCopyStep from './CardCopyStep';
|
||||
|
||||
export default withPopup(CardCopyStep);
|
167
client/src/components/CardCopyStep/CardCopyStep.jsx
Normal file
167
client/src/components/CardCopyStep/CardCopyStep.jsx
Normal file
|
@ -0,0 +1,167 @@
|
|||
import React, { useMemo, useCallback } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Dropdown, Form, TextArea, Checkbox } from 'semantic-ui-react';
|
||||
import { Popup } from '../../lib/custom-ui';
|
||||
|
||||
import { useForm } from '../../hooks';
|
||||
|
||||
import styles from './CardCopyStep.module.scss';
|
||||
|
||||
const CardCopyStep = React.memo(
|
||||
({ projectsToLists, defaultPath, onMove, onTransfer, onBoardFetch, onBack, onClose }) => {
|
||||
const [t] = useTranslation();
|
||||
|
||||
const [path, handleFieldChange] = useForm(() => ({
|
||||
projectId: null,
|
||||
boardId: null,
|
||||
listId: null,
|
||||
name: null,
|
||||
description: null,
|
||||
tasks: [],
|
||||
attachments: [],
|
||||
labels: [],
|
||||
users: [],
|
||||
...defaultPath,
|
||||
}));
|
||||
|
||||
const selectedProject = useMemo(
|
||||
() => projectsToLists.find((project) => project.id === path.projectId) || null,
|
||||
[projectsToLists, path.projectId],
|
||||
);
|
||||
|
||||
const selectedBoard = useMemo(
|
||||
() =>
|
||||
(selectedProject && selectedProject.boards.find((board) => board.id === path.boardId)) ||
|
||||
null,
|
||||
[selectedProject, path.boardId],
|
||||
);
|
||||
|
||||
const selectedList = useMemo(
|
||||
() => (selectedBoard && selectedBoard.lists.find((list) => list.id === path.listId)) || null,
|
||||
[selectedBoard, path.listId],
|
||||
);
|
||||
|
||||
const handleBoardIdChange = useCallback(
|
||||
(event, data) => {
|
||||
if (selectedProject.boards.find((board) => board.id === data.value).isFetching === null) {
|
||||
onBoardFetch(data.value);
|
||||
}
|
||||
|
||||
handleFieldChange(event, data);
|
||||
},
|
||||
[onBoardFetch, handleFieldChange, selectedProject],
|
||||
);
|
||||
|
||||
const handleSubmit = useCallback(() => {
|
||||
if (selectedBoard.id !== defaultPath.boardId) {
|
||||
onTransfer(selectedBoard.id, selectedList.id);
|
||||
} else if (selectedList.id !== defaultPath.listId) {
|
||||
onMove(selectedList.id);
|
||||
}
|
||||
|
||||
onClose();
|
||||
}, [defaultPath, onMove, onTransfer, onClose, selectedBoard, selectedList]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Popup.Header onBack={onBack}>
|
||||
{t('Copy Card', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Popup.Header>
|
||||
<Popup.Content>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<div className={styles.text}>{t('common.project')}</div>
|
||||
<Dropdown
|
||||
fluid
|
||||
selection
|
||||
name="projectId"
|
||||
options={projectsToLists.map((project) => ({
|
||||
text: project.name,
|
||||
value: project.id,
|
||||
}))}
|
||||
value={selectedProject && selectedProject.id}
|
||||
placeholder={
|
||||
projectsToLists.length === 0 ? t('common.noProjects') : t('common.selectProject')
|
||||
}
|
||||
disabled={projectsToLists.length === 0}
|
||||
className={styles.field}
|
||||
onChange={handleFieldChange}
|
||||
/>
|
||||
{selectedProject && (
|
||||
<>
|
||||
<div className={styles.text}>{t('common.board')}</div>
|
||||
<Dropdown
|
||||
fluid
|
||||
selection
|
||||
name="boardId"
|
||||
options={selectedProject.boards.map((board) => ({
|
||||
text: board.name,
|
||||
value: board.id,
|
||||
}))}
|
||||
value={selectedBoard && selectedBoard.id}
|
||||
placeholder={
|
||||
selectedProject.boards.length === 0
|
||||
? t('common.noBoards')
|
||||
: t('common.selectBoard')
|
||||
}
|
||||
disabled={selectedProject.boards.length === 0}
|
||||
className={styles.field}
|
||||
onChange={handleBoardIdChange}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{selectedBoard && (
|
||||
<>
|
||||
<div className={styles.text}>{t('common.list')}</div>
|
||||
<Dropdown
|
||||
fluid
|
||||
selection
|
||||
name="listId"
|
||||
options={selectedBoard.lists.map((list) => ({
|
||||
text: list.name,
|
||||
value: list.id,
|
||||
}))}
|
||||
value={selectedList && selectedList.id}
|
||||
placeholder={
|
||||
selectedBoard.isFetching === false && selectedBoard.lists.length === 0
|
||||
? t('common.noLists')
|
||||
: t('common.selectList')
|
||||
}
|
||||
loading={selectedBoard.isFetching !== false}
|
||||
disabled={selectedBoard.isFetching !== false || selectedBoard.lists.length === 0}
|
||||
className={styles.field}
|
||||
onChange={handleFieldChange}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Button
|
||||
positive
|
||||
content={t('Copy')} // change this action.copy
|
||||
disabled={(selectedBoard && selectedBoard.isFetching !== false) || !selectedList}
|
||||
/>
|
||||
</Form>
|
||||
</Popup.Content>
|
||||
</>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
CardCopyStep.propTypes = {
|
||||
/* eslint-disable react/forbid-prop-types */
|
||||
projectsToLists: PropTypes.array.isRequired,
|
||||
defaultPath: PropTypes.object.isRequired,
|
||||
/* eslint-enable react/forbid-prop-types */
|
||||
onMove: PropTypes.func.isRequired,
|
||||
onTransfer: PropTypes.func.isRequired,
|
||||
onBoardFetch: PropTypes.func.isRequired,
|
||||
onBack: PropTypes.func,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
CardCopyStep.defaultProps = {
|
||||
onBack: undefined,
|
||||
};
|
||||
|
||||
export default CardCopyStep;
|
12
client/src/components/CardCopyStep/CardCopyStep.module.scss
Normal file
12
client/src/components/CardCopyStep/CardCopyStep.module.scss
Normal file
|
@ -0,0 +1,12 @@
|
|||
:global(#app) {
|
||||
.field {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: #444444;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
}
|
3
client/src/components/CardCopyStep/index.js
Normal file
3
client/src/components/CardCopyStep/index.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
import CardCopyStep from './CardCopyStep';
|
||||
|
||||
export default CardCopyStep;
|
|
@ -23,7 +23,7 @@ import DueDateEditPopup from '../DueDateEditPopup';
|
|||
import TimerEditPopup from '../TimerEditPopup';
|
||||
import CardMovePopup from '../CardMovePopup';
|
||||
import DeletePopup from '../DeletePopup';
|
||||
|
||||
import CardCopyPopup from '../CardCopyPopup';
|
||||
import styles from './CardModal.module.scss';
|
||||
|
||||
const CardModal = React.memo(
|
||||
|
@ -477,6 +477,32 @@ const CardModal = React.memo(
|
|||
{t('action.move')}
|
||||
</Button>
|
||||
</CardMovePopup>
|
||||
<CardCopyPopup
|
||||
projectsToLists={allProjectsToLists}
|
||||
defaultPath={{
|
||||
name,
|
||||
description,
|
||||
users,
|
||||
labels,
|
||||
tasks,
|
||||
attachments,
|
||||
projectId,
|
||||
boardId,
|
||||
listId,
|
||||
}}
|
||||
onMove={onMove}
|
||||
onTransfer={onTransfer}
|
||||
onBoardFetch={onBoardFetch}
|
||||
>
|
||||
<Button
|
||||
fluid
|
||||
className={styles.actionButton}
|
||||
// onClick={handleToggleSubscriptionClick}
|
||||
>
|
||||
<Icon name="copy outline" className={styles.actionIcon} />
|
||||
{t('Copy')}
|
||||
</Button>
|
||||
</CardCopyPopup>
|
||||
<DeletePopup
|
||||
title={t('common.deleteCard', {
|
||||
context: 'title',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue