mirror of
https://github.com/plankanban/planka.git
synced 2025-08-10 16:05:35 +02:00
Added card archiving functionality and created status column with corresponding migrations
- Implemented the option to archive cards in the system, with support in both backend and frontend. - Created 'status' column in the cards table to manage archiving status. - Developed necessary database migrations for the new column. - Reused the delete confirmation popup to confirm archiving, minimizing code changes. - Modifications made to backend handlers and frontend UI to support the archiving functionality.
This commit is contained in:
parent
03825c3bed
commit
60c514b63f
49 changed files with 174 additions and 37 deletions
|
@ -49,6 +49,13 @@ updateCard.success = (card) => ({
|
|||
},
|
||||
});
|
||||
|
||||
updateCard.archive_success = (card) => ({
|
||||
type: ActionTypes.CARD_ARCHIVE__SUCCESS,
|
||||
payload: {
|
||||
card,
|
||||
},
|
||||
});
|
||||
|
||||
updateCard.failure = (id, error) => ({
|
||||
type: ActionTypes.CARD_UPDATE__FAILURE,
|
||||
payload: {
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Button, Form } from 'semantic-ui-react';
|
|||
import { Input, Popup } from '../../lib/custom-ui';
|
||||
|
||||
import { useForm, useSteps } from '../../hooks';
|
||||
import DeleteStep from '../DeleteStep';
|
||||
import ConfirmStep from '../ConfirmStep';
|
||||
|
||||
import styles from './EditStep.module.scss';
|
||||
|
||||
|
@ -54,7 +54,7 @@ const EditStep = React.memo(({ defaultData, onUpdate, onDelete, onClose }) => {
|
|||
|
||||
if (step && step.type === StepTypes.DELETE) {
|
||||
return (
|
||||
<DeleteStep
|
||||
<ConfirmStep
|
||||
title="common.deleteBoard"
|
||||
content="common.areYouSureYouWantToDeleteThisBoard"
|
||||
buttonContent="action.deleteBoard"
|
||||
|
|
|
@ -11,9 +11,10 @@ import LabelsStep from '../LabelsStep';
|
|||
import DueDateEditStep from '../DueDateEditStep';
|
||||
import StopwatchEditStep from '../StopwatchEditStep';
|
||||
import CardMoveStep from '../CardMoveStep';
|
||||
import DeleteStep from '../DeleteStep';
|
||||
import ConfirmStep from '../ConfirmStep';
|
||||
|
||||
import styles from './ActionsStep.module.scss';
|
||||
import { CardStatus } from '../../constants/Enums';
|
||||
|
||||
const StepTypes = {
|
||||
USERS: 'USERS',
|
||||
|
@ -22,6 +23,7 @@ const StepTypes = {
|
|||
EDIT_STOPWATCH: 'EDIT_STOPWATCH',
|
||||
MOVE: 'MOVE',
|
||||
DELETE: 'DELETE',
|
||||
ARCHIVE: 'ARCHIVE',
|
||||
};
|
||||
|
||||
const ActionsStep = React.memo(
|
||||
|
@ -48,6 +50,7 @@ const ActionsStep = React.memo(
|
|||
onLabelMove,
|
||||
onLabelDelete,
|
||||
onClose,
|
||||
onArchive,
|
||||
}) => {
|
||||
const [t] = useTranslation();
|
||||
const [step, openStep, handleBack] = useSteps();
|
||||
|
@ -82,6 +85,10 @@ const ActionsStep = React.memo(
|
|||
onClose();
|
||||
}, [onDuplicate, onClose]);
|
||||
|
||||
const handleArchiveClick = useCallback(() => {
|
||||
openStep(StepTypes.ARCHIVE);
|
||||
}, [openStep]);
|
||||
|
||||
const handleDeleteClick = useCallback(() => {
|
||||
openStep(StepTypes.DELETE);
|
||||
}, [openStep]);
|
||||
|
@ -162,7 +169,7 @@ const ActionsStep = React.memo(
|
|||
);
|
||||
case StepTypes.DELETE:
|
||||
return (
|
||||
<DeleteStep
|
||||
<ConfirmStep
|
||||
title="common.deleteCard"
|
||||
content="common.areYouSureYouWantToDeleteThisCard"
|
||||
buttonContent="action.deleteCard"
|
||||
|
@ -170,6 +177,16 @@ const ActionsStep = React.memo(
|
|||
onBack={handleBack}
|
||||
/>
|
||||
);
|
||||
case StepTypes.ARCHIVE:
|
||||
return (
|
||||
<ConfirmStep
|
||||
title="common.archiveCard_title"
|
||||
content="common.areYouSureYouWantToArchiveThisCard"
|
||||
buttonContent="action.archiveCard"
|
||||
onConfirm={onArchive}
|
||||
onBack={handleBack}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
@ -218,6 +235,11 @@ const ActionsStep = React.memo(
|
|||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleArchiveClick}>
|
||||
{t('action.archiveCard', {
|
||||
context: 'title',
|
||||
})}
|
||||
</Menu.Item>
|
||||
<Menu.Item className={styles.menuItem} onClick={handleDeleteClick}>
|
||||
{t('action.deleteCard', {
|
||||
context: 'title',
|
||||
|
@ -255,6 +277,7 @@ ActionsStep.propTypes = {
|
|||
onLabelMove: PropTypes.func.isRequired,
|
||||
onLabelDelete: PropTypes.func.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onArchive: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default ActionsStep;
|
||||
|
|
|
@ -17,6 +17,7 @@ import DueDate from '../DueDate';
|
|||
import Stopwatch from '../Stopwatch';
|
||||
|
||||
import styles from './Card.module.scss';
|
||||
import { CardStatus } from '../../constants/Enums';
|
||||
|
||||
const Card = React.memo(
|
||||
({
|
||||
|
@ -81,6 +82,13 @@ const Card = React.memo(
|
|||
[onUpdate],
|
||||
);
|
||||
|
||||
const handleArchiveClick = useCallback(() => {
|
||||
onUpdate({
|
||||
status: CardStatus.ARCHIVED,
|
||||
});
|
||||
onClose();
|
||||
}, [onUpdate]);
|
||||
|
||||
const handleNameEdit = useCallback(() => {
|
||||
nameEdit.current.open();
|
||||
}, []);
|
||||
|
@ -197,6 +205,7 @@ const Card = React.memo(
|
|||
onLabelUpdate={onLabelUpdate}
|
||||
onLabelMove={onLabelMove}
|
||||
onLabelDelete={onLabelDelete}
|
||||
onArchive={handleArchiveClick}
|
||||
>
|
||||
<Button className={classNames(styles.actionsButton, styles.target)}>
|
||||
<Icon fitted name="pencil" size="small" />
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Markdown } from '../../../lib/custom-ui';
|
|||
import getDateFormat from '../../../utils/get-date-format';
|
||||
import CommentEdit from './CommentEdit';
|
||||
import User from '../../User';
|
||||
import DeleteStep from '../../DeleteStep';
|
||||
import ConfirmStep from '../../ConfirmStep';
|
||||
|
||||
import styles from './ItemComment.module.scss';
|
||||
|
||||
|
@ -23,7 +23,7 @@ const ItemComment = React.memo(
|
|||
commentEdit.current.open();
|
||||
}, []);
|
||||
|
||||
const DeletePopup = usePopup(DeleteStep);
|
||||
const DeletePopup = usePopup(ConfirmStep);
|
||||
|
||||
return (
|
||||
<Comment>
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Button, Form } from 'semantic-ui-react';
|
|||
import { Input, Popup } from '../../../lib/custom-ui';
|
||||
|
||||
import { useForm, useSteps } from '../../../hooks';
|
||||
import DeleteStep from '../../DeleteStep';
|
||||
import ConfirmStep from '../../ConfirmStep';
|
||||
|
||||
import styles from './EditStep.module.scss';
|
||||
|
||||
|
@ -54,7 +54,7 @@ const EditStep = React.memo(({ defaultData, onUpdate, onDelete, onClose }) => {
|
|||
|
||||
if (step && step.type === StepTypes.DELETE) {
|
||||
return (
|
||||
<DeleteStep
|
||||
<ConfirmStep
|
||||
title="common.deleteAttachment"
|
||||
content="common.areYouSureYouWantToDeleteThisAttachment"
|
||||
buttonContent="action.deleteAttachment"
|
||||
|
|
|
@ -23,9 +23,10 @@ import LabelsStep from '../LabelsStep';
|
|||
import DueDateEditStep from '../DueDateEditStep';
|
||||
import StopwatchEditStep from '../StopwatchEditStep';
|
||||
import CardMoveStep from '../CardMoveStep';
|
||||
import DeleteStep from '../DeleteStep';
|
||||
import ConfirmStep from '../ConfirmStep';
|
||||
|
||||
import styles from './CardModal.module.scss';
|
||||
import { CardStatus } from '../../constants/Enums';
|
||||
|
||||
const CardModal = React.memo(
|
||||
({
|
||||
|
@ -141,6 +142,13 @@ const CardModal = React.memo(
|
|||
});
|
||||
}, [isSubscribed, onUpdate]);
|
||||
|
||||
const handleArchiveClick = useCallback(() => {
|
||||
onUpdate({
|
||||
status: CardStatus.ARCHIVED,
|
||||
});
|
||||
onClose();
|
||||
}, [onUpdate, onClose]);
|
||||
|
||||
const handleDuplicateClick = useCallback(() => {
|
||||
onDuplicate();
|
||||
onClose();
|
||||
|
@ -168,7 +176,7 @@ const CardModal = React.memo(
|
|||
const DueDateEditPopup = usePopup(DueDateEditStep);
|
||||
const StopwatchEditPopup = usePopup(StopwatchEditStep);
|
||||
const CardMovePopup = usePopup(CardMoveStep);
|
||||
const DeletePopup = usePopup(DeleteStep);
|
||||
const DeletePopup = usePopup(ConfirmStep);
|
||||
|
||||
const userIds = users.map((user) => user.id);
|
||||
const labelIds = labels.map((label) => label.id);
|
||||
|
@ -506,6 +514,19 @@ const CardModal = React.memo(
|
|||
<Icon name="copy outline" className={styles.actionIcon} />
|
||||
{t('action.duplicate')}
|
||||
</Button>
|
||||
|
||||
<DeletePopup
|
||||
title="common.archiveCard"
|
||||
content="common.areYouSureYouWantToArchiveThisCard"
|
||||
buttonContent="action.archiveCard"
|
||||
onConfirm={handleArchiveClick}
|
||||
>
|
||||
<Button fluid className={styles.actionButton}>
|
||||
<Icon name="archive icon" className={styles.actionIcon} />
|
||||
{t('action.archive')}
|
||||
</Button>
|
||||
</DeletePopup>
|
||||
|
||||
<DeletePopup
|
||||
title="common.deleteCard"
|
||||
content="common.areYouSureYouWantToDeleteThisCard"
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Menu } from 'semantic-ui-react';
|
|||
import { Popup } from '../../../lib/custom-ui';
|
||||
|
||||
import { useSteps } from '../../../hooks';
|
||||
import DeleteStep from '../../DeleteStep';
|
||||
import ConfirmStep from '../../ConfirmStep';
|
||||
|
||||
import styles from './ActionsStep.module.scss';
|
||||
|
||||
|
@ -28,7 +28,7 @@ const ActionsStep = React.memo(({ onNameEdit, onDelete, onClose }) => {
|
|||
|
||||
if (step && step.type === StepTypes.DELETE) {
|
||||
return (
|
||||
<DeleteStep
|
||||
<ConfirmStep
|
||||
title="common.deleteTask"
|
||||
content="common.areYouSureYouWantToDeleteThisTask"
|
||||
buttonContent="action.deleteTask"
|
||||
|
|
|
@ -4,9 +4,9 @@ import { useTranslation } from 'react-i18next';
|
|||
import { Button } from 'semantic-ui-react';
|
||||
import { Popup } from '../../lib/custom-ui';
|
||||
|
||||
import styles from './DeleteStep.module.scss';
|
||||
import styles from './ConfirmStep.module.scss';
|
||||
|
||||
const DeleteStep = React.memo(({ title, content, buttonContent, onConfirm, onBack }) => {
|
||||
const ConfirmStep = React.memo(({ title, content, buttonContent, onConfirm, onBack }) => {
|
||||
const [t] = useTranslation();
|
||||
|
||||
return (
|
||||
|
@ -24,7 +24,7 @@ const DeleteStep = React.memo(({ title, content, buttonContent, onConfirm, onBac
|
|||
);
|
||||
});
|
||||
|
||||
DeleteStep.propTypes = {
|
||||
ConfirmStep.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
content: PropTypes.string.isRequired,
|
||||
buttonContent: PropTypes.string.isRequired,
|
||||
|
@ -32,8 +32,8 @@ DeleteStep.propTypes = {
|
|||
onBack: PropTypes.func,
|
||||
};
|
||||
|
||||
DeleteStep.defaultProps = {
|
||||
ConfirmStep.defaultProps = {
|
||||
onBack: undefined,
|
||||
};
|
||||
|
||||
export default DeleteStep;
|
||||
export default ConfirmStep;
|
3
client/src/components/ConfirmStep/index.js
Normal file
3
client/src/components/ConfirmStep/index.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
import ConfirmStep from './ConfirmStep';
|
||||
|
||||
export default ConfirmStep;
|
|
@ -1,3 +0,0 @@
|
|||
import DeleteStep from './DeleteStep';
|
||||
|
||||
export default DeleteStep;
|
|
@ -8,7 +8,7 @@ import { Popup } from '../../lib/custom-ui';
|
|||
import { useForm, useSteps } from '../../hooks';
|
||||
import LabelColors from '../../constants/LabelColors';
|
||||
import Editor from './Editor';
|
||||
import DeleteStep from '../DeleteStep';
|
||||
import ConfirmStep from '../ConfirmStep';
|
||||
|
||||
import styles from './EditStep.module.scss';
|
||||
|
||||
|
@ -46,7 +46,7 @@ const EditStep = React.memo(({ defaultData, onUpdate, onDelete, onBack }) => {
|
|||
|
||||
if (step && step.type === StepTypes.DELETE) {
|
||||
return (
|
||||
<DeleteStep
|
||||
<ConfirmStep
|
||||
title="common.deleteLabel"
|
||||
content="common.areYouSureYouWantToDeleteThisLabel"
|
||||
buttonContent="action.deleteLabel"
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Menu } from 'semantic-ui-react';
|
|||
import { Popup } from '../../lib/custom-ui';
|
||||
|
||||
import { useSteps } from '../../hooks';
|
||||
import DeleteStep from '../DeleteStep';
|
||||
import ConfirmStep from '../ConfirmStep';
|
||||
|
||||
import styles from './ActionsStep.module.scss';
|
||||
|
||||
|
@ -33,7 +33,7 @@ const ActionsStep = React.memo(({ onNameEdit, onCardAdd, onDelete, onClose }) =>
|
|||
|
||||
if (step && step.type === StepTypes.DELETE) {
|
||||
return (
|
||||
<DeleteStep
|
||||
<ConfirmStep
|
||||
title="common.deleteList"
|
||||
content="common.areYouSureYouWantToDeleteThisList"
|
||||
buttonContent="action.deleteList"
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Button } from 'semantic-ui-react';
|
|||
|
||||
import { useSteps } from '../../hooks';
|
||||
import User from '../User';
|
||||
import DeleteStep from '../DeleteStep';
|
||||
import ConfirmStep from '../ConfirmStep';
|
||||
|
||||
import styles from './ActionsStep.module.scss';
|
||||
|
||||
|
@ -71,7 +71,7 @@ const ActionsStep = React.memo(
|
|||
}
|
||||
case StepTypes.DELETE:
|
||||
return (
|
||||
<DeleteStep
|
||||
<ConfirmStep
|
||||
title={membership.user.isCurrent ? leaveConfirmationTitle : deleteConfirmationTitle}
|
||||
content={
|
||||
membership.user.isCurrent ? leaveConfirmationContent : deleteConfirmationContent
|
||||
|
|
|
@ -5,14 +5,14 @@ import { Button, Divider, Header, Tab } from 'semantic-ui-react';
|
|||
import { usePopup } from '../../../lib/popup';
|
||||
|
||||
import InformationEdit from './InformationEdit';
|
||||
import DeleteStep from '../../DeleteStep';
|
||||
import ConfirmStep from '../../ConfirmStep';
|
||||
|
||||
import styles from './GeneralPane.module.scss';
|
||||
|
||||
const GeneralPane = React.memo(({ name, onUpdate, onDelete }) => {
|
||||
const [t] = useTranslation();
|
||||
|
||||
const DeletePopup = usePopup(DeleteStep);
|
||||
const DeletePopup = usePopup(ConfirmStep);
|
||||
|
||||
return (
|
||||
<Tab.Pane attached={false} className={styles.wrapper}>
|
||||
|
|
|
@ -10,7 +10,7 @@ import UserInformationEditStep from '../../UserInformationEditStep';
|
|||
import UserUsernameEditStep from '../../UserUsernameEditStep';
|
||||
import UserEmailEditStep from '../../UserEmailEditStep';
|
||||
import UserPasswordEditStep from '../../UserPasswordEditStep';
|
||||
import DeleteStep from '../../DeleteStep';
|
||||
import ConfirmStep from '../../ConfirmStep';
|
||||
|
||||
import styles from './ActionsStep.module.scss';
|
||||
|
||||
|
@ -110,7 +110,7 @@ const ActionsStep = React.memo(
|
|||
);
|
||||
case StepTypes.DELETE:
|
||||
return (
|
||||
<DeleteStep
|
||||
<ConfirmStep
|
||||
title="common.deleteUser"
|
||||
content="common.areYouSureYouWantToDeleteThisUser"
|
||||
buttonContent="action.deleteUser"
|
||||
|
|
|
@ -201,6 +201,7 @@ export default {
|
|||
CARD_DELETE__SUCCESS: 'CARD_DELETE__SUCCESS',
|
||||
CARD_DELETE__FAILURE: 'CARD_DELETE__FAILURE',
|
||||
CARD_DELETE_HANDLE: 'CARD_DELETE_HANDLE',
|
||||
CARD_ARCHIVE__SUCCESS: 'CARD_ARCHIVE__SUCCESS',
|
||||
|
||||
/* Tasks */
|
||||
|
||||
|
|
|
@ -13,3 +13,8 @@ export const ActivityTypes = {
|
|||
MOVE_CARD: 'moveCard',
|
||||
COMMENT_CARD: 'commentCard',
|
||||
};
|
||||
|
||||
export const CardStatus = {
|
||||
ACTIVE: 'active',
|
||||
ARCHIVED: 'archived',
|
||||
};
|
||||
|
|
|
@ -184,6 +184,7 @@ export default {
|
|||
createLabel: 'Vytvořit štítek',
|
||||
createNewLabel: 'Vytvořit nový štítek',
|
||||
createProject: 'Vytvořit projekt',
|
||||
archive: 'Archivovat',
|
||||
delete: 'Smazat',
|
||||
deleteAttachment: 'Smazat přílohu',
|
||||
deleteAvatar: 'Smazat avatar',
|
||||
|
|
|
@ -164,6 +164,7 @@ export default {
|
|||
createLabel: 'Opret mærkat',
|
||||
createNewLabel: 'Opret nyt mærkat',
|
||||
createProject: 'Opret projekt',
|
||||
archive: 'Archivovat',
|
||||
delete: 'Slet',
|
||||
deleteAttachment: 'Slet vedhæftning',
|
||||
deleteAvatar: 'Slet profilbillede',
|
||||
|
|
|
@ -174,6 +174,7 @@ export default {
|
|||
createLabel: 'Label erstellen',
|
||||
createNewLabel: 'Neues Label erstellen',
|
||||
createProject: 'Projekt erstellen',
|
||||
archive: 'Archivieren',
|
||||
delete: 'Löschen',
|
||||
deleteAttachment: 'Anhang löschen',
|
||||
deleteAvatar: 'Avatar löschen',
|
||||
|
|
|
@ -26,6 +26,7 @@ export default {
|
|||
areYouSureYouWantToDeleteThisAttachment: 'Are you sure you want to delete this attachment?',
|
||||
areYouSureYouWantToDeleteThisBoard: 'Are you sure you want to delete this board?',
|
||||
areYouSureYouWantToDeleteThisCard: 'Are you sure you want to delete this card?',
|
||||
areYouSureYouWantToArchiveThisCard: 'Are you sure you want to archive this card?',
|
||||
areYouSureYouWantToDeleteThisComment: 'Are you sure you want to delete this comment?',
|
||||
areYouSureYouWantToDeleteThisLabel: 'Are you sure you want to delete this label?',
|
||||
areYouSureYouWantToDeleteThisList: 'Are you sure you want to delete this list?',
|
||||
|
@ -64,6 +65,7 @@ export default {
|
|||
deleteAttachment_title: 'Delete Attachment',
|
||||
deleteBoard_title: 'Delete Board',
|
||||
deleteCard_title: 'Delete Card',
|
||||
archiveCard_title: 'Archive Card',
|
||||
deleteComment_title: 'Delete Comment',
|
||||
deleteLabel_title: 'Delete Label',
|
||||
deleteList_title: 'Delete List',
|
||||
|
@ -181,12 +183,15 @@ export default {
|
|||
createLabel: 'Create label',
|
||||
createNewLabel: 'Create new label',
|
||||
createProject: 'Create project',
|
||||
archive: 'Archive',
|
||||
delete: 'Delete',
|
||||
deleteAttachment: 'Delete attachment',
|
||||
deleteAvatar: 'Delete avatar',
|
||||
deleteBoard: 'Delete board',
|
||||
deleteCard: 'Delete card',
|
||||
deleteCard_title: 'Delete Card',
|
||||
archiveCard_title: 'Archive Card',
|
||||
archiveCard: 'Archive card',
|
||||
deleteComment: 'Delete comment',
|
||||
deleteImage: 'Delete image',
|
||||
deleteLabel: 'Delete label',
|
||||
|
|
|
@ -28,6 +28,7 @@ export default {
|
|||
areYouSureYouWantToDeleteThisAttachment: '¿Estás seguro de que quieres borrar este adjunto?',
|
||||
areYouSureYouWantToDeleteThisBoard: '¿Estás seguro de que quieres borrar este tablero?',
|
||||
areYouSureYouWantToDeleteThisCard: '¿Estás seguro de que quieres borrar esta tarjeta?',
|
||||
areYouSureYouWantToArchiveThisCard: '¿Estás seguro de que quieres archivar esta tarjeta?',
|
||||
areYouSureYouWantToDeleteThisComment: '¿Estás seguro de que quieres borrar este comentario?',
|
||||
areYouSureYouWantToDeleteThisLabel: '¿Estás seguro de que quieres borrar esta etiqueta?',
|
||||
areYouSureYouWantToDeleteThisList: '¿Estás seguro de que quieres borrar esta lista?',
|
||||
|
@ -56,6 +57,7 @@ export default {
|
|||
deleteAttachment_title: 'Eliminar Adjunto',
|
||||
deleteBoard_title: 'Borrar Tablero',
|
||||
deleteCard_title: 'Borrar tarjeta',
|
||||
archiveCard_title: 'Archivar Tarjeta',
|
||||
deleteComment_title: 'Borrar Comentario',
|
||||
deleteLabel_title: 'Borrar Etiqueta',
|
||||
deleteList_title: 'Borrar Lista',
|
||||
|
@ -153,12 +155,15 @@ export default {
|
|||
createLabel: 'Crear etiqueta',
|
||||
createNewLabel: 'Crear una nueva etiqueta',
|
||||
createProject: 'Crear proyecto',
|
||||
archive: 'Archivar',
|
||||
delete: 'Borrar',
|
||||
deleteAttachment: 'Borrar adjuntos',
|
||||
deleteAvatar: 'Borrar avatar',
|
||||
deleteBoard: 'Borrar tablero',
|
||||
deleteCard: 'Borrar tarjeta',
|
||||
deleteCard_title: 'Borrar tarjeta',
|
||||
archiveCard: 'Archivar tarjeta',
|
||||
archiveCard_title: 'Archivar Tarjeta',
|
||||
deleteComment: 'Borrar comentario',
|
||||
deleteImage: 'Borrar imagen',
|
||||
deleteLabel: 'Borrar etiqueta',
|
||||
|
|
|
@ -153,6 +153,7 @@ export default {
|
|||
createLabel: 'Créer une étiquette',
|
||||
createNewLabel: 'Créer une nouvelle étiquette',
|
||||
createProject: 'Créer un projet',
|
||||
archive: 'Archiver',
|
||||
delete: 'Supprimer',
|
||||
deleteAttachment: 'Supprimer la pièce jointe',
|
||||
deleteAvatar: "Supprimer l'avatar",
|
||||
|
|
|
@ -175,6 +175,7 @@ export default {
|
|||
createLabel: 'Címke létrehozása',
|
||||
createNewLabel: 'Új címke létrehozása',
|
||||
createProject: 'Projekt létrehozása',
|
||||
archive: 'Archiválás',
|
||||
delete: 'Törlés',
|
||||
deleteAttachment: 'Melléklet törlése',
|
||||
deleteAvatar: 'Avatar törlése',
|
||||
|
|
|
@ -185,6 +185,7 @@ export default {
|
|||
createLabel: 'Tambah label',
|
||||
createNewLabel: 'Tambah label baru',
|
||||
createProject: 'Tambah proyek',
|
||||
archive: 'Arsipkan',
|
||||
delete: 'Hapus',
|
||||
deleteAttachment: 'Hapus lampiran',
|
||||
deleteAvatar: 'Hapus avatar',
|
||||
|
|
|
@ -180,6 +180,7 @@ export default {
|
|||
createLabel: 'Crea etichetta',
|
||||
createNewLabel: 'Crea nuova etichetta',
|
||||
createProject: 'Crea progetto',
|
||||
archive: 'Archiviare',
|
||||
delete: 'Elimina',
|
||||
deleteAttachment: 'Elimina allegato',
|
||||
deleteAvatar: 'Elimina avatar',
|
||||
|
|
|
@ -185,6 +185,7 @@ export default {
|
|||
createLabel: 'ラベルを作成',
|
||||
createNewLabel: '新しいラベルを作成',
|
||||
createProject: 'プロジェクトを作成',
|
||||
archive: 'アーカイブ',
|
||||
delete: '削除',
|
||||
deleteAttachment: '添付ファイルを削除',
|
||||
deleteAvatar: 'アバターを削除',
|
||||
|
|
|
@ -186,6 +186,7 @@ export default {
|
|||
createLabel: 'Label aanmaken',
|
||||
createNewLabel: 'Nieuw label aanmaken',
|
||||
createProject: 'Project aanmaken',
|
||||
archive: 'Archiveren',
|
||||
delete: 'Verwijderen',
|
||||
deleteAttachment: 'Bijlage verwijderen',
|
||||
deleteAvatar: 'Avatar verwijderen',
|
||||
|
|
|
@ -153,6 +153,7 @@ export default {
|
|||
createLabel: 'Utwórz oznaczenie',
|
||||
createNewLabel: 'Utwórz nowe oznaczenie',
|
||||
createProject: 'Utwórz projekt',
|
||||
archive: 'Archiwizować',
|
||||
delete: 'Usuń',
|
||||
deleteAttachment: 'Usuń załącznik',
|
||||
deleteAvatar: 'Usuń avatar',
|
||||
|
|
|
@ -30,6 +30,7 @@ export default {
|
|||
areYouSureYouWantToDeleteThisAttachment: 'Tem certeza de que deseja excluir este anexo?',
|
||||
areYouSureYouWantToDeleteThisBoard: 'Tem certeza de que deseja excluir este quadro?',
|
||||
areYouSureYouWantToDeleteThisCard: 'Tem certeza de que deseja excluir este cartão?',
|
||||
areYouSureYouWantToArchiveThisCard: 'Tem certeza de que deseja arquivar este cartão?',
|
||||
areYouSureYouWantToDeleteThisComment: 'Tem certeza de que deseja excluir este comentário?',
|
||||
areYouSureYouWantToDeleteThisLabel: 'Tem certeza de que deseja excluir este rótulo?',
|
||||
areYouSureYouWantToDeleteThisList: 'Tem certeza de que deseja excluir esta lista?',
|
||||
|
@ -67,6 +68,7 @@ export default {
|
|||
deleteAttachment_title: 'Excluir Anexo',
|
||||
deleteBoard_title: 'Excluir Quadro',
|
||||
deleteCard_title: 'Excluir Cartão',
|
||||
archiveCard_title: 'Arquivar Cartão',
|
||||
deleteComment_title: 'Excluir Comentário',
|
||||
deleteLabel_title: 'Excluir Rótulo',
|
||||
deleteList_title: 'Excluir Lista',
|
||||
|
@ -185,12 +187,15 @@ export default {
|
|||
createLabel: 'Criar rótulo',
|
||||
createNewLabel: 'Criar novo rótulo',
|
||||
createProject: 'Criar projeto',
|
||||
archive: 'Arquivar',
|
||||
delete: 'Excluir',
|
||||
deleteAttachment: 'Excluir anexo',
|
||||
deleteAvatar: 'Excluir avatar',
|
||||
deleteBoard: 'Excluir quadro',
|
||||
deleteCard: 'Excluir cartão',
|
||||
deleteCard_title: 'Excluir Cartão',
|
||||
archiveCard: 'Arquivar cartão',
|
||||
archiveCard_title: 'Arquivar Cartão',
|
||||
deleteComment: 'Excluir comentário',
|
||||
deleteImage: 'Excluir imagem',
|
||||
deleteLabel: 'Excluir rótulo',
|
||||
|
|
|
@ -186,6 +186,7 @@ export default {
|
|||
createLabel: 'Creați eticheta',
|
||||
createNewLabel: 'Creați o nouă etichetă',
|
||||
createProject: 'Creați proiect',
|
||||
archive: 'Arhiva',
|
||||
delete: 'Ștergeți',
|
||||
deleteAttachment: 'Ștergeți atașamentul',
|
||||
deleteAvatar: 'Ștergeți avatarul',
|
||||
|
|
|
@ -187,6 +187,7 @@ export default {
|
|||
createLabel: 'Создать метку',
|
||||
createNewLabel: 'Создать новую метку',
|
||||
createProject: 'Создать проект',
|
||||
archive: 'Архивировать',
|
||||
delete: 'Удалить',
|
||||
deleteAttachment: 'Удалить вложение',
|
||||
deleteAvatar: 'Удалить аватар',
|
||||
|
|
|
@ -165,6 +165,7 @@ export default {
|
|||
createLabel: 'Vytvoriť štítok',
|
||||
createNewLabel: 'Vytvoriť nový štítok',
|
||||
createProject: 'Vytvoriť projekt',
|
||||
archive: 'Archivovať',
|
||||
delete: 'Zmazať',
|
||||
deleteAttachment: 'Zmazať prílohu',
|
||||
deleteAvatar: 'Zmazať avatar',
|
||||
|
|
|
@ -167,6 +167,7 @@ export default {
|
|||
createLabel: 'Skapa etikett',
|
||||
createNewLabel: 'Skapa ny etikett',
|
||||
createProject: 'Skapa projekt',
|
||||
archive: 'Arkivera',
|
||||
delete: 'Ta Bort',
|
||||
deleteAttachment: 'Ta bort bilaga',
|
||||
deleteAvatar: 'Ta bort avatar',
|
||||
|
|
|
@ -168,6 +168,7 @@ export default {
|
|||
createLabel: 'Etiket Oluştur',
|
||||
createNewLabel: 'Yeni etiket oluştur',
|
||||
createProject: 'Proje oluştur',
|
||||
archive: 'Arşivlemek',
|
||||
delete: 'Sil',
|
||||
deleteAttachment: 'Eki sil',
|
||||
deleteAvatar: 'Avatarı sil',
|
||||
|
|
|
@ -181,6 +181,7 @@ export default {
|
|||
createLabel: 'Створити мітку',
|
||||
createNewLabel: 'Створити нову мітку',
|
||||
createProject: 'Створити проект',
|
||||
archive: 'Архівувати',
|
||||
delete: 'Видалити',
|
||||
deleteAttachment: 'Видалити вкладення',
|
||||
deleteAvatar: 'Видалити аватар',
|
||||
|
|
|
@ -160,6 +160,7 @@ export default {
|
|||
createLabel: 'Yorliq yaratish',
|
||||
createNewLabel: 'Yangi yorliq yaratish',
|
||||
createProject: 'Loyiha yaratish',
|
||||
archive: 'Arxivlash',
|
||||
delete: "O'chirish",
|
||||
deleteAttachment: "Ilovani o'chirish",
|
||||
deleteAvatar: "Avatarni o'chirish",
|
||||
|
|
|
@ -177,6 +177,7 @@ export default {
|
|||
createLabel: '创建标签',
|
||||
createNewLabel: '创建新标签',
|
||||
createProject: '创建项目',
|
||||
archive: '归档',
|
||||
delete: '删除',
|
||||
deleteAttachment: '删除附件',
|
||||
deleteAvatar: '删除头像',
|
||||
|
|
|
@ -4,7 +4,7 @@ import { attr, fk, many, oneToOne } from 'redux-orm';
|
|||
import BaseModel from './BaseModel';
|
||||
import ActionTypes from '../constants/ActionTypes';
|
||||
import Config from '../constants/Config';
|
||||
import { ActivityTypes } from '../constants/Enums';
|
||||
import { ActivityTypes, CardStatus } from '../constants/Enums';
|
||||
|
||||
export default class extends BaseModel {
|
||||
static modelName = 'Card';
|
||||
|
@ -16,6 +16,9 @@ export default class extends BaseModel {
|
|||
description: attr(),
|
||||
dueDate: attr(),
|
||||
stopwatch: attr(),
|
||||
status: attr({
|
||||
getDefault: () => CardStatus.ACTIVE,
|
||||
}),
|
||||
isSubscribed: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
|
@ -202,6 +205,7 @@ export default class extends BaseModel {
|
|||
'listId',
|
||||
'position',
|
||||
'name',
|
||||
'status',
|
||||
'description',
|
||||
'dueDate',
|
||||
'stopwatch',
|
||||
|
@ -235,9 +239,9 @@ export default class extends BaseModel {
|
|||
}
|
||||
case ActionTypes.CARD_DELETE:
|
||||
Card.withId(payload.id).deleteWithRelated();
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_DELETE__SUCCESS:
|
||||
case ActionTypes.CARD_ARCHIVE__SUCCESS:
|
||||
case ActionTypes.CARD_DELETE_HANDLE: {
|
||||
const cardModel = Card.withId(payload.card.id);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import actions from '../../../actions';
|
|||
import api from '../../../api';
|
||||
import i18n from '../../../i18n';
|
||||
import { createLocalId } from '../../../utils/local-id';
|
||||
import { CardStatus } from '../../../constants/Enums';
|
||||
|
||||
export function* createCard(listId, data, autoOpen) {
|
||||
const { boardId } = yield select(selectors.selectListById, listId);
|
||||
|
@ -63,7 +64,6 @@ export function* handleCardCreate({ id }) {
|
|||
|
||||
export function* updateCard(id, data) {
|
||||
yield put(actions.updateCard(id, data));
|
||||
|
||||
let card;
|
||||
try {
|
||||
({ item: card } = yield call(request, api.updateCard, id, data));
|
||||
|
@ -72,6 +72,10 @@ export function* updateCard(id, data) {
|
|||
return;
|
||||
}
|
||||
|
||||
if ('status' in data && data.status === CardStatus.ARCHIVED) {
|
||||
yield put(actions.updateCard.archive_success(card));
|
||||
return;
|
||||
}
|
||||
yield put(actions.updateCard.success(card));
|
||||
}
|
||||
|
||||
|
|
|
@ -75,10 +75,10 @@ services:
|
|||
dockerfile: ../config/development/Dockerfile.server
|
||||
environment:
|
||||
- DATABASE_URL=postgresql://user:password@postgres:5432/planka_db
|
||||
# - DEFAULT_ADMIN_EMAIL=demo@demo.demo # Do not remove if you want to prevent this user from being edited/deleted
|
||||
# - DEFAULT_ADMIN_PASSWORD=demo
|
||||
# - DEFAULT_ADMIN_NAME=Demo Demo
|
||||
# - DEFAULT_ADMIN_USERNAME=demo
|
||||
- DEFAULT_ADMIN_EMAIL=admin@robsonvnt.me # Do not remove if you want to prevent this user from being edited/deleted
|
||||
- DEFAULT_ADMIN_PASSWORD=admin
|
||||
- DEFAULT_ADMIN_NAME=Admin
|
||||
- DEFAULT_ADMIN_USERNAME=admin
|
||||
|
||||
working_dir: /app
|
||||
command: ["sh", "-c", "npm run db:init"]
|
||||
|
|
|
@ -44,6 +44,11 @@ module.exports = {
|
|||
position: {
|
||||
type: 'number',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
isIn: ['active', 'archived'],
|
||||
defaultsTo: 'active',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
|
|
|
@ -87,6 +87,10 @@ module.exports = {
|
|||
isSubscribed: {
|
||||
type: 'boolean',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
isIn: ['active', 'archived'],
|
||||
},
|
||||
},
|
||||
|
||||
exits: {
|
||||
|
@ -173,6 +177,7 @@ module.exports = {
|
|||
'dueDate',
|
||||
'stopwatch',
|
||||
'isSubscribed',
|
||||
'status',
|
||||
]);
|
||||
|
||||
card = await sails.helpers.cards.updateOne
|
||||
|
|
|
@ -12,6 +12,7 @@ module.exports = {
|
|||
async fn(inputs) {
|
||||
return sails.helpers.cards.getMany({
|
||||
boardId: inputs.idOrIds,
|
||||
status: inputs.status || 'active',
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -28,6 +28,13 @@ module.exports = {
|
|||
type: 'ref',
|
||||
columnName: 'due_date',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
isIn: ['active', 'archived'],
|
||||
defaultsTo: 'active',
|
||||
allowNull: false,
|
||||
description: 'The current status of the card, which can be active or archived.',
|
||||
},
|
||||
stopwatch: {
|
||||
type: 'json',
|
||||
},
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
exports.up = async (knex) => {
|
||||
await knex.schema.table('card', (table) => {
|
||||
table.enum('status', ['active', 'archived']).defaultTo('active').notNullable();
|
||||
});
|
||||
};
|
||||
|
||||
exports.down = async (knex) => {
|
||||
await knex.schema.table('card', (table) => {
|
||||
table.dropColumn('status');
|
||||
});
|
||||
};
|
|
@ -7,6 +7,7 @@
|
|||
"db:init": "node db/init.js",
|
||||
"db:migrate": "knex migrate:latest --cwd db",
|
||||
"db:seed": "knex seed:run --cwd db",
|
||||
"db:create-migration": "knex migrate:make --cwd db",
|
||||
"lint": "eslint . --max-warnings=0 --report-unused-disable-directives && echo '✔ Your .js files look good.'",
|
||||
"start": "nodemon",
|
||||
"start:prod": "node app.js --prod",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue