pull/724/merge
Robson Ventura 2 years ago committed by GitHub
commit fbf04da80a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1 +1,3 @@
# Planka client
# Frontend
The Planka frontend uses a combination of React, Redux, and Saga for state management and side effects, providing a rich and responsive user experience.

@ -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;

@ -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',
@ -182,12 +184,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',
@ -186,12 +188,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"]

@ -1 +1,53 @@
# Planka server
# Planka Server Documentation
The backend was developed using the SailsJS framework, which facilitates complex operations in web applications, especially when combined with the Knex database migration manager.
## Modifying the Database Structure
### Creating a Migration
**Step 1:** Navigate to the corresponding folder within the project:
```bash
cd ROOT_PATH/server/db
```
**Step 2:** Execute the following command to create a new migration file:
```bash
npm run db:create-migration add_change_in_the_database_structure
```
This command creates a file in the migration folder named based on the provided argument. The generated file will have the following initial structure:
```Javascript
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.up = function(knex) {
// Add the changes that will be applied to the database
};
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.down = function(knex) {
// Add the changes that will revert the operations done in up
};
```
#### Adapting to Asynchronous Functions:
In the project, asynchronous functions are used by default. Modify the migration file to adhere to this standard:
```Javascript
exports.up = async (knex) => {
// Migration logic to apply changes
};
exports.down = async (knex) => {
// Migration logic to revert changes
};
```
#### Implementation
Implement the necessary logic in the up and down methods to apply or revert changes in the database. To understand how migrations work and explore detailed examples, refer to the [official Knex documentation on migrations](https://knexjs.org/guide/migrations.html#migration-api).

@ -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…
Cancel
Save