mirror of
https://github.com/plankanban/planka.git
synced 2025-07-18 20:59:44 +02:00
feat: Add board activity log
This commit is contained in:
parent
777ff467f3
commit
86cfd155f2
72 changed files with 833 additions and 169 deletions
|
@ -5,15 +5,39 @@
|
||||||
|
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
const fetchActivities = (cardId) => ({
|
const fetchActivitiesInBoard = (boardId) => ({
|
||||||
type: ActionTypes.ACTIVITIES_FETCH,
|
type: ActionTypes.ACTIVITIES_IN_BOARD_FETCH,
|
||||||
|
payload: {
|
||||||
|
boardId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
fetchActivitiesInBoard.success = (boardId, activities, users) => ({
|
||||||
|
type: ActionTypes.ACTIVITIES_IN_BOARD_FETCH__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
boardId,
|
||||||
|
activities,
|
||||||
|
users,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
fetchActivitiesInBoard.failure = (boardId, error) => ({
|
||||||
|
type: ActionTypes.ACTIVITIES_IN_BOARD_FETCH__FAILURE,
|
||||||
|
payload: {
|
||||||
|
boardId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchActivitiesInCard = (cardId) => ({
|
||||||
|
type: ActionTypes.ACTIVITIES_IN_CARD_FETCH,
|
||||||
payload: {
|
payload: {
|
||||||
cardId,
|
cardId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
fetchActivities.success = (cardId, activities, users) => ({
|
fetchActivitiesInCard.success = (cardId, activities, users) => ({
|
||||||
type: ActionTypes.ACTIVITIES_FETCH__SUCCESS,
|
type: ActionTypes.ACTIVITIES_IN_CARD_FETCH__SUCCESS,
|
||||||
payload: {
|
payload: {
|
||||||
cardId,
|
cardId,
|
||||||
activities,
|
activities,
|
||||||
|
@ -21,8 +45,8 @@ fetchActivities.success = (cardId, activities, users) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
fetchActivities.failure = (cardId, error) => ({
|
fetchActivitiesInCard.failure = (cardId, error) => ({
|
||||||
type: ActionTypes.ACTIVITIES_FETCH__FAILURE,
|
type: ActionTypes.ACTIVITIES_IN_CARD_FETCH__FAILURE,
|
||||||
payload: {
|
payload: {
|
||||||
cardId,
|
cardId,
|
||||||
error,
|
error,
|
||||||
|
@ -37,6 +61,7 @@ const handleActivityCreate = (activity) => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
fetchActivities,
|
fetchActivitiesInBoard,
|
||||||
|
fetchActivitiesInCard,
|
||||||
handleActivityCreate,
|
handleActivityCreate,
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,13 @@ export const transformActivity = (activity) => ({
|
||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const getActivities = (cardId, data, headers) =>
|
const getActivitiesInBoard = (boardId, data, headers) =>
|
||||||
|
socket.get(`/boards/${boardId}/actions`, data, headers).then((body) => ({
|
||||||
|
...body,
|
||||||
|
items: body.items.map(transformActivity),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const getActivitiesInCard = (cardId, data, headers) =>
|
||||||
socket.get(`/cards/${cardId}/actions`, data, headers).then((body) => ({
|
socket.get(`/cards/${cardId}/actions`, data, headers).then((body) => ({
|
||||||
...body,
|
...body,
|
||||||
items: body.items.map(transformActivity),
|
items: body.items.map(transformActivity),
|
||||||
|
@ -32,6 +38,7 @@ const makeHandleActivityCreate = (next) => (body) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getActivities,
|
getActivitiesInBoard,
|
||||||
|
getActivitiesInCard,
|
||||||
makeHandleActivityCreate,
|
makeHandleActivityCreate,
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useCallback } from 'react';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useInView } from 'react-intersection-observer';
|
||||||
|
import { Comment, Loader } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
import selectors from '../../../selectors';
|
||||||
|
import entryActions from '../../../entry-actions';
|
||||||
|
import { useClosableModal } from '../../../hooks';
|
||||||
|
import Item from './Item';
|
||||||
|
|
||||||
|
import styles from './BoardActivitiesModal.module.scss';
|
||||||
|
|
||||||
|
const BoardActivitiesModal = React.memo(() => {
|
||||||
|
const activityIds = useSelector(selectors.selectActivityIdsForCurrentBoard);
|
||||||
|
|
||||||
|
const { isActivitiesFetching, isAllActivitiesFetched } = useSelector(
|
||||||
|
selectors.selectCurrentBoard,
|
||||||
|
);
|
||||||
|
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
const handleClose = useCallback(() => {
|
||||||
|
dispatch(entryActions.closeModal());
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
const [inViewRef] = useInView({
|
||||||
|
threshold: 1,
|
||||||
|
onChange: (inView) => {
|
||||||
|
if (inView) {
|
||||||
|
dispatch(entryActions.fetchActivitiesInCurrentBoard());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [ClosableModal] = useClosableModal();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ClosableModal closeIcon size="small" centered={false} onClose={handleClose}>
|
||||||
|
<ClosableModal.Header>
|
||||||
|
{t('common.boardActions', {
|
||||||
|
context: 'title',
|
||||||
|
})}
|
||||||
|
</ClosableModal.Header>
|
||||||
|
<ClosableModal.Content>
|
||||||
|
<div className={styles.itemsWrapper}>
|
||||||
|
<Comment.Group className={styles.items}>
|
||||||
|
{activityIds.map((activityId) => (
|
||||||
|
<Item key={activityId} id={activityId} />
|
||||||
|
))}
|
||||||
|
</Comment.Group>
|
||||||
|
</div>
|
||||||
|
{isActivitiesFetching !== undefined && isAllActivitiesFetched !== undefined && (
|
||||||
|
<div className={styles.loaderWrapper}>
|
||||||
|
{isActivitiesFetching ? (
|
||||||
|
<Loader active inverted inline="centered" size="small" />
|
||||||
|
) : (
|
||||||
|
!isAllActivitiesFetched && <div ref={inViewRef} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</ClosableModal.Content>
|
||||||
|
</ClosableModal>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default BoardActivitiesModal;
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
:global(#app) {
|
||||||
|
.items {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.itemsWrapper {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loaderWrapper {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
220
client/src/components/activities/BoardActivitiesModal/Item.jsx
Executable file
220
client/src/components/activities/BoardActivitiesModal/Item.jsx
Executable file
|
@ -0,0 +1,220 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { useTranslation, Trans } from 'react-i18next';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { Comment } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
import selectors from '../../../selectors';
|
||||||
|
import Paths from '../../../constants/Paths';
|
||||||
|
import { StaticUserIds } from '../../../constants/StaticUsers';
|
||||||
|
import { ActivityTypes } from '../../../constants/Enums';
|
||||||
|
import TimeAgo from '../../common/TimeAgo';
|
||||||
|
import UserAvatar from '../../users/UserAvatar';
|
||||||
|
|
||||||
|
import styles from './Item.module.scss';
|
||||||
|
|
||||||
|
const Item = React.memo(({ id }) => {
|
||||||
|
const selectActivityById = useMemo(() => selectors.makeSelectActivityById(), []);
|
||||||
|
const selectUserById = useMemo(() => selectors.makeSelectUserById(), []);
|
||||||
|
const selectCardById = useMemo(() => selectors.makeSelectCardById(), []);
|
||||||
|
|
||||||
|
const activity = useSelector((state) => selectActivityById(state, id));
|
||||||
|
const user = useSelector((state) => selectUserById(state, activity.userId));
|
||||||
|
const card = useSelector((state) => selectCardById(state, activity.cardId));
|
||||||
|
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
const userName =
|
||||||
|
user.id === StaticUserIds.DELETED
|
||||||
|
? t(`common.${user.name}`, {
|
||||||
|
context: 'title',
|
||||||
|
})
|
||||||
|
: user.name;
|
||||||
|
|
||||||
|
const cardName = card ? card.name : activity.data.card.name;
|
||||||
|
|
||||||
|
let contentNode;
|
||||||
|
switch (activity.type) {
|
||||||
|
case ActivityTypes.CREATE_CARD: {
|
||||||
|
const { list } = activity.data;
|
||||||
|
const listName = list.name || t(`common.${list.type}`);
|
||||||
|
|
||||||
|
contentNode = (
|
||||||
|
<Trans
|
||||||
|
i18nKey="common.userAddedCardToList"
|
||||||
|
values={{
|
||||||
|
user: userName,
|
||||||
|
card: cardName,
|
||||||
|
list: listName,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className={styles.author}>{userName}</span>
|
||||||
|
{' added '}
|
||||||
|
<Link to={Paths.CARDS.replace(':id', activity.cardId)}>{cardName}</Link>
|
||||||
|
{' to '}
|
||||||
|
{listName}
|
||||||
|
</Trans>
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ActivityTypes.MOVE_CARD: {
|
||||||
|
const { fromList, toList } = activity.data;
|
||||||
|
|
||||||
|
const fromListName = fromList.name || t(`common.${fromList.type}`);
|
||||||
|
const toListName = toList.name || t(`common.${toList.type}`);
|
||||||
|
|
||||||
|
contentNode = (
|
||||||
|
<Trans
|
||||||
|
i18nKey="common.userMovedCardFromListToList"
|
||||||
|
values={{
|
||||||
|
user: userName,
|
||||||
|
card: cardName,
|
||||||
|
fromList: fromListName,
|
||||||
|
toList: toListName,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className={styles.author}>{userName}</span>
|
||||||
|
{' moved '}
|
||||||
|
<Link to={Paths.CARDS.replace(':id', activity.cardId)}>{cardName}</Link>
|
||||||
|
{' from '}
|
||||||
|
{fromListName}
|
||||||
|
{' to '}
|
||||||
|
{toListName}
|
||||||
|
</Trans>
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ActivityTypes.ADD_MEMBER_TO_CARD:
|
||||||
|
contentNode =
|
||||||
|
user.id === activity.data.user.id ? (
|
||||||
|
<Trans
|
||||||
|
i18nKey="common.userJoinedCard"
|
||||||
|
values={{
|
||||||
|
user: userName,
|
||||||
|
card: cardName,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className={styles.author}>{userName}</span>
|
||||||
|
{' joined '}
|
||||||
|
<Link to={Paths.CARDS.replace(':id', activity.cardId)}>{cardName}</Link>
|
||||||
|
</Trans>
|
||||||
|
) : (
|
||||||
|
<Trans
|
||||||
|
i18nKey="common.userAddedUserToCard"
|
||||||
|
values={{
|
||||||
|
actorUser: userName,
|
||||||
|
addedUser: activity.data.user.name,
|
||||||
|
card: cardName,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className={styles.author}>{userName}</span>
|
||||||
|
{' added '}
|
||||||
|
{activity.data.user.name}
|
||||||
|
{' to '}
|
||||||
|
<Link to={Paths.CARDS.replace(':id', activity.cardId)}>{cardName}</Link>
|
||||||
|
</Trans>
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ActivityTypes.REMOVE_MEMBER_FROM_CARD:
|
||||||
|
contentNode =
|
||||||
|
user.id === activity.data.user.id ? (
|
||||||
|
<Trans
|
||||||
|
i18nKey="common.userLeftCard"
|
||||||
|
values={{
|
||||||
|
user: userName,
|
||||||
|
card: cardName,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className={styles.author}>{userName}</span>
|
||||||
|
{' left '}
|
||||||
|
<Link to={Paths.CARDS.replace(':id', activity.cardId)}>{cardName}</Link>
|
||||||
|
</Trans>
|
||||||
|
) : (
|
||||||
|
<Trans
|
||||||
|
i18nKey="common.userRemovedUserFromCard"
|
||||||
|
values={{
|
||||||
|
actorUser: userName,
|
||||||
|
removedUser: activity.data.user.name,
|
||||||
|
card: cardName,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className={styles.author}>{userName}</span>
|
||||||
|
{' removed '}
|
||||||
|
{activity.data.user.name}
|
||||||
|
{' from '}
|
||||||
|
<Link to={Paths.CARDS.replace(':id', activity.cardId)}>{cardName}</Link>
|
||||||
|
</Trans>
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ActivityTypes.COMPLETE_TASK:
|
||||||
|
contentNode = (
|
||||||
|
<Trans
|
||||||
|
i18nKey="common.userCompletedTaskOnCard"
|
||||||
|
values={{
|
||||||
|
user: userName,
|
||||||
|
task: activity.data.task.name,
|
||||||
|
card: cardName,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className={styles.author}>{userName}</span>
|
||||||
|
{' completed '}
|
||||||
|
{activity.data.task.name}
|
||||||
|
{' on '}
|
||||||
|
<Link to={Paths.CARDS.replace(':id', activity.cardId)}>{cardName}</Link>
|
||||||
|
</Trans>
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ActivityTypes.UNCOMPLETE_TASK:
|
||||||
|
contentNode = (
|
||||||
|
<Trans
|
||||||
|
i18nKey="common.userMarkedTaskIncompleteOnCard"
|
||||||
|
values={{
|
||||||
|
user: userName,
|
||||||
|
task: activity.data.task.name,
|
||||||
|
card: cardName,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className={styles.author}>{userName}</span>
|
||||||
|
{' marked '}
|
||||||
|
{activity.data.task.name}
|
||||||
|
{' incomplete on '}
|
||||||
|
<Link to={Paths.CARDS.replace(':id', activity.cardId)}>{cardName}</Link>
|
||||||
|
</Trans>
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
contentNode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Comment>
|
||||||
|
<span className={styles.user}>
|
||||||
|
<UserAvatar id={activity.userId} />
|
||||||
|
</span>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<div>{contentNode}</div>
|
||||||
|
<span className={styles.date}>
|
||||||
|
<TimeAgo date={activity.createdAt} />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Comment>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Item.propTypes = {
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Item;
|
|
@ -7,12 +7,12 @@
|
||||||
.author {
|
.author {
|
||||||
color: #17394d;
|
color: #17394d;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
line-height: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
border-bottom: 1px solid #092d4221;
|
border-bottom: 1px solid #092d4221;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
line-height: 20px;
|
||||||
padding-bottom: 14px;
|
padding-bottom: 14px;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
width: calc(100% - 40px);
|
width: calc(100% - 40px);
|
||||||
|
@ -21,11 +21,6 @@
|
||||||
.date {
|
.date {
|
||||||
color: #6b808c;
|
color: #6b808c;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text {
|
|
||||||
line-height: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.user {
|
.user {
|
8
client/src/components/activities/BoardActivitiesModal/index.js
Executable file
8
client/src/components/activities/BoardActivitiesModal/index.js
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import BoardActivitiesModal from './BoardActivitiesModal';
|
||||||
|
|
||||||
|
export default BoardActivitiesModal;
|
|
@ -12,9 +12,9 @@ import selectors from '../../../selectors';
|
||||||
import entryActions from '../../../entry-actions';
|
import entryActions from '../../../entry-actions';
|
||||||
import Item from './Item';
|
import Item from './Item';
|
||||||
|
|
||||||
import styles from './Activities.module.scss';
|
import styles from './CardActivities.module.scss';
|
||||||
|
|
||||||
const Activities = React.memo(() => {
|
const CardActivities = React.memo(() => {
|
||||||
const activityIds = useSelector(selectors.selectActivityIdsForCurrentCard);
|
const activityIds = useSelector(selectors.selectActivityIdsForCurrentCard);
|
||||||
const { isActivitiesFetching, isAllActivitiesFetched } = useSelector(selectors.selectCurrentCard);
|
const { isActivitiesFetching, isAllActivitiesFetched } = useSelector(selectors.selectCurrentCard);
|
||||||
|
|
||||||
|
@ -51,4 +51,4 @@ const Activities = React.memo(() => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
export default Activities;
|
export default CardActivities;
|
|
@ -48,10 +48,8 @@ const Item = React.memo(({ id }) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className={styles.author}>{userName}</span>
|
<span className={styles.author}>{userName}</span>
|
||||||
<span className={styles.text}>
|
{' added this card to '}
|
||||||
{' added this card to '}
|
{listName}
|
||||||
{listName}
|
|
||||||
</span>
|
|
||||||
</Trans>
|
</Trans>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -73,12 +71,10 @@ const Item = React.memo(({ id }) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className={styles.author}>{userName}</span>
|
<span className={styles.author}>{userName}</span>
|
||||||
<span className={styles.text}>
|
{' moved this card from '}
|
||||||
{' moved this card from '}
|
{fromListName}
|
||||||
{fromListName}
|
{' to '}
|
||||||
{' to '}
|
{toListName}
|
||||||
{toListName}
|
|
||||||
</span>
|
|
||||||
</Trans>
|
</Trans>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -94,7 +90,7 @@ const Item = React.memo(({ id }) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className={styles.author}>{userName}</span>
|
<span className={styles.author}>{userName}</span>
|
||||||
<span className={styles.text}>{' joined this card'}</span>
|
{' joined this card'}
|
||||||
</Trans>
|
</Trans>
|
||||||
) : (
|
) : (
|
||||||
<Trans
|
<Trans
|
||||||
|
@ -105,11 +101,9 @@ const Item = React.memo(({ id }) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className={styles.author}>{userName}</span>
|
<span className={styles.author}>{userName}</span>
|
||||||
<span className={styles.text}>
|
{' added '}
|
||||||
{' added '}
|
{activity.data.user.name}
|
||||||
{activity.data.user.name}
|
{' to this card'}
|
||||||
{' to this card'}
|
|
||||||
</span>
|
|
||||||
</Trans>
|
</Trans>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -124,7 +118,7 @@ const Item = React.memo(({ id }) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className={styles.author}>{userName}</span>
|
<span className={styles.author}>{userName}</span>
|
||||||
<span className={styles.text}>{' left this card'}</span>
|
{' left this card'}
|
||||||
</Trans>
|
</Trans>
|
||||||
) : (
|
) : (
|
||||||
<Trans
|
<Trans
|
||||||
|
@ -135,11 +129,9 @@ const Item = React.memo(({ id }) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className={styles.author}>{userName}</span>
|
<span className={styles.author}>{userName}</span>
|
||||||
<span className={styles.text}>
|
{' removed '}
|
||||||
{' removed '}
|
{activity.data.user.name}
|
||||||
{activity.data.user.name}
|
{' from this card'}
|
||||||
{' from this card'}
|
|
||||||
</span>
|
|
||||||
</Trans>
|
</Trans>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -154,11 +146,9 @@ const Item = React.memo(({ id }) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className={styles.author}>{userName}</span>
|
<span className={styles.author}>{userName}</span>
|
||||||
<span className={styles.text}>
|
{' completed '}
|
||||||
{' completed '}
|
{activity.data.task.name}
|
||||||
{activity.data.task.name}
|
{' on this card'}
|
||||||
{' on this card'}
|
|
||||||
</span>
|
|
||||||
</Trans>
|
</Trans>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -173,11 +163,9 @@ const Item = React.memo(({ id }) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className={styles.author}>{userName}</span>
|
<span className={styles.author}>{userName}</span>
|
||||||
<span className={styles.text}>
|
{' marked '}
|
||||||
{' marked '}
|
{activity.data.task.name}
|
||||||
{activity.data.task.name}
|
{' incomplete on this card'}
|
||||||
{' incomplete on this card'}
|
|
||||||
</span>
|
|
||||||
</Trans>
|
</Trans>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
:global(#app) {
|
||||||
|
.author {
|
||||||
|
color: #17394d;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
border-bottom: 1px solid #092d4221;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 20px;
|
||||||
|
padding-bottom: 14px;
|
||||||
|
vertical-align: top;
|
||||||
|
width: calc(100% - 40px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.date {
|
||||||
|
color: #6b808c;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px 8px 0 0;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,6 @@
|
||||||
* 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 Activities from './Activities';
|
import CardActivities from './CardActivities';
|
||||||
|
|
||||||
export default Activities;
|
export default CardActivities;
|
|
@ -7,14 +7,17 @@ import React from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
import selectors from '../../../selectors';
|
import selectors from '../../../selectors';
|
||||||
|
import ModalTypes from '../../../constants/ModalTypes';
|
||||||
import { BoardContexts, BoardViews } from '../../../constants/Enums';
|
import { BoardContexts, BoardViews } from '../../../constants/Enums';
|
||||||
import KanbanContent from './KanbanContent';
|
import KanbanContent from './KanbanContent';
|
||||||
import FiniteContent from './FiniteContent';
|
import FiniteContent from './FiniteContent';
|
||||||
import EndlessContent from './EndlessContent';
|
import EndlessContent from './EndlessContent';
|
||||||
import CardModal from '../../cards/CardModal';
|
import CardModal from '../../cards/CardModal';
|
||||||
|
import BoardActivitiesModal from '../../activities/BoardActivitiesModal';
|
||||||
|
|
||||||
const Board = React.memo(() => {
|
const Board = React.memo(() => {
|
||||||
const board = useSelector(selectors.selectCurrentBoard);
|
const board = useSelector(selectors.selectCurrentBoard);
|
||||||
|
const modal = useSelector(selectors.selectCurrentModal);
|
||||||
const isCardModalOpened = useSelector((state) => !!selectors.selectPath(state).cardId);
|
const isCardModalOpened = useSelector((state) => !!selectors.selectPath(state).cardId);
|
||||||
|
|
||||||
let Content;
|
let Content;
|
||||||
|
@ -35,10 +38,23 @@ const Board = React.memo(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let modalNode = null;
|
||||||
|
if (isCardModalOpened) {
|
||||||
|
modalNode = <CardModal />;
|
||||||
|
} else if (modal) {
|
||||||
|
switch (modal.type) {
|
||||||
|
case ModalTypes.BOARD_ACTIVITIES:
|
||||||
|
modalNode = <BoardActivitiesModal />;
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Content />
|
<Content />
|
||||||
{isCardModalOpened && <CardModal />}
|
{modalNode}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,14 +21,14 @@ import CustomFieldGroupsStep from '../../../custom-field-groups/CustomFieldGroup
|
||||||
import styles from './ActionsStep.module.scss';
|
import styles from './ActionsStep.module.scss';
|
||||||
|
|
||||||
const StepTypes = {
|
const StepTypes = {
|
||||||
EMPTY_TRASH: 'EMPTY_TRASH',
|
|
||||||
CUSTOM_FIELD_GROUPS: 'CUSTOM_FIELD_GROUPS',
|
CUSTOM_FIELD_GROUPS: 'CUSTOM_FIELD_GROUPS',
|
||||||
|
EMPTY_TRASH: 'EMPTY_TRASH',
|
||||||
};
|
};
|
||||||
|
|
||||||
const ActionsStep = React.memo(({ onClose }) => {
|
const ActionsStep = React.memo(({ onClose }) => {
|
||||||
const board = useSelector(selectors.selectCurrentBoard);
|
const board = useSelector(selectors.selectCurrentBoard);
|
||||||
|
|
||||||
const { withSubscribe, withTrashEmptier, withCustomFieldGroups } = useSelector((state) => {
|
const { withSubscribe, withCustomFieldGroups, withTrashEmptier } = useSelector((state) => {
|
||||||
const isManager = selectors.selectIsCurrentUserManagerForCurrentProject(state);
|
const isManager = selectors.selectIsCurrentUserManagerForCurrentProject(state);
|
||||||
const boardMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
|
const boardMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ const ActionsStep = React.memo(({ onClose }) => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
withSubscribe: isMember, // TODO: rename?
|
withSubscribe: isMember, // TODO: rename?
|
||||||
withTrashEmptier: board.context === BoardContexts.TRASH && (isManager || isEditor),
|
|
||||||
withCustomFieldGroups: isEditor,
|
withCustomFieldGroups: isEditor,
|
||||||
|
withTrashEmptier: board.context === BoardContexts.TRASH && (isManager || isEditor),
|
||||||
};
|
};
|
||||||
}, shallowEqual);
|
}, shallowEqual);
|
||||||
|
|
||||||
|
@ -69,21 +69,28 @@ const ActionsStep = React.memo(({ onClose }) => {
|
||||||
[onClose, dispatch],
|
[onClose, dispatch],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleActivitiesClick = useCallback(() => {
|
||||||
|
dispatch(entryActions.openBoardActivitiesModal());
|
||||||
|
onClose();
|
||||||
|
}, [onClose, dispatch]);
|
||||||
|
|
||||||
const handleEmptyTrashConfirm = useCallback(() => {
|
const handleEmptyTrashConfirm = useCallback(() => {
|
||||||
dispatch(entryActions.clearTrashListInCurrentBoard());
|
dispatch(entryActions.clearTrashListInCurrentBoard());
|
||||||
onClose();
|
onClose();
|
||||||
}, [onClose, dispatch]);
|
}, [onClose, dispatch]);
|
||||||
|
|
||||||
const handleEmptyTrashClick = useCallback(() => {
|
|
||||||
openStep(StepTypes.EMPTY_TRASH);
|
|
||||||
}, [openStep]);
|
|
||||||
|
|
||||||
const handleCustomFieldsClick = useCallback(() => {
|
const handleCustomFieldsClick = useCallback(() => {
|
||||||
openStep(StepTypes.CUSTOM_FIELD_GROUPS);
|
openStep(StepTypes.CUSTOM_FIELD_GROUPS);
|
||||||
}, [openStep]);
|
}, [openStep]);
|
||||||
|
|
||||||
|
const handleEmptyTrashClick = useCallback(() => {
|
||||||
|
openStep(StepTypes.EMPTY_TRASH);
|
||||||
|
}, [openStep]);
|
||||||
|
|
||||||
if (step) {
|
if (step) {
|
||||||
switch (step.type) {
|
switch (step.type) {
|
||||||
|
case StepTypes.CUSTOM_FIELD_GROUPS:
|
||||||
|
return <CustomFieldGroupsStep onBack={handleBack} onClose={onClose} />;
|
||||||
case StepTypes.EMPTY_TRASH:
|
case StepTypes.EMPTY_TRASH:
|
||||||
return (
|
return (
|
||||||
<ConfirmationStep
|
<ConfirmationStep
|
||||||
|
@ -94,8 +101,6 @@ const ActionsStep = React.memo(({ onClose }) => {
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case StepTypes.CUSTOM_FIELD_GROUPS:
|
|
||||||
return <CustomFieldGroupsStep onBack={handleBack} onClose={onClose} />;
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,6 +133,12 @@ const ActionsStep = React.memo(({ onClose }) => {
|
||||||
})}
|
})}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
)}
|
)}
|
||||||
|
<Menu.Item className={styles.menuItem} onClick={handleActivitiesClick}>
|
||||||
|
<Icon name="list ul" className={styles.menuItemIcon} />
|
||||||
|
{t('common.actions', {
|
||||||
|
context: 'title',
|
||||||
|
})}
|
||||||
|
</Menu.Item>
|
||||||
{withTrashEmptier && (
|
{withTrashEmptier && (
|
||||||
<>
|
<>
|
||||||
{(withSubscribe || withCustomFieldGroups) && <hr className={styles.divider} />}
|
{(withSubscribe || withCustomFieldGroups) && <hr className={styles.divider} />}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { Menu, Tab } from 'semantic-ui-react';
|
import { Menu, Tab } from 'semantic-ui-react';
|
||||||
|
|
||||||
import Comments from '../../comments/Comments';
|
import Comments from '../../comments/Comments';
|
||||||
import Activities from '../../activities/Activities';
|
import CardActivities from '../../activities/CardActivities';
|
||||||
|
|
||||||
import styles from './Communication.module.scss';
|
import styles from './Communication.module.scss';
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ const Communication = React.memo(() => {
|
||||||
})}
|
})}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
),
|
),
|
||||||
render: () => <Activities />,
|
render: () => <CardActivities />,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
.content {
|
.content {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
line-height: 20px;
|
||||||
min-height: 36px;
|
min-height: 36px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 0 4px 0 8px;
|
padding: 0 4px 0 8px;
|
||||||
|
@ -40,7 +41,6 @@
|
||||||
.date {
|
.date {
|
||||||
color: #6b808c;
|
color: #6b808c;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
|
|
@ -360,9 +360,12 @@ export default {
|
||||||
|
|
||||||
/* Activities */
|
/* Activities */
|
||||||
|
|
||||||
ACTIVITIES_FETCH: 'ACTIVITIES_FETCH',
|
ACTIVITIES_IN_BOARD_FETCH: 'ACTIVITIES_IN_BOARD_FETCH',
|
||||||
ACTIVITIES_FETCH__SUCCESS: 'ACTIVITIES_FETCH__SUCCESS',
|
ACTIVITIES_IN_BOARD_FETCH__SUCCESS: 'ACTIVITIES_IN_BOARD_FETCH__SUCCESS',
|
||||||
ACTIVITIES_FETCH__FAILURE: 'ACTIVITIES_FETCH__FAILURE',
|
ACTIVITIES_IN_BOARD_FETCH__FAILURE: 'ACTIVITIES_IN_BOARD_FETCH__FAILURE',
|
||||||
|
ACTIVITIES_IN_CARD_FETCH: 'ACTIVITIES_IN_CARD_FETCH',
|
||||||
|
ACTIVITIES_IN_CARD_FETCH__SUCCESS: 'ACTIVITIES_IN_CARD_FETCH__SUCCESS',
|
||||||
|
ACTIVITIES_IN_CARD_FETCH__FAILURE: 'ACTIVITIES_IN_CARD_FETCH__FAILURE',
|
||||||
ACTIVITY_CREATE_HANDLE: 'ACTIVITY_CREATE_HANDLE',
|
ACTIVITY_CREATE_HANDLE: 'ACTIVITY_CREATE_HANDLE',
|
||||||
|
|
||||||
/* Notifications */
|
/* Notifications */
|
||||||
|
|
|
@ -255,6 +255,7 @@ export default {
|
||||||
|
|
||||||
/* Activities */
|
/* Activities */
|
||||||
|
|
||||||
|
ACTIVITIES_IN_CURRENT_BOARD_FETCH: `${PREFIX}/ACTIVITIES_IN_CURRENT_BOARD_FETCH`,
|
||||||
ACTIVITIES_IN_CURRENT_CARD_FETCH: `${PREFIX}/ACTIVITIES_IN_CURRENT_CARD_FETCH`,
|
ACTIVITIES_IN_CURRENT_CARD_FETCH: `${PREFIX}/ACTIVITIES_IN_CURRENT_CARD_FETCH`,
|
||||||
ACTIVITY_CREATE_HANDLE: `${PREFIX}/ACTIVITY_CREATE_HANDLE`,
|
ACTIVITY_CREATE_HANDLE: `${PREFIX}/ACTIVITY_CREATE_HANDLE`,
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ const USER_SETTINGS = 'USER_SETTINGS';
|
||||||
const ADD_PROJECT = 'ADD_PROJECT';
|
const ADD_PROJECT = 'ADD_PROJECT';
|
||||||
const PROJECT_SETTINGS = 'PROJECT_SETTINGS';
|
const PROJECT_SETTINGS = 'PROJECT_SETTINGS';
|
||||||
const BOARD_SETTINGS = 'BOARD_SETTINGS';
|
const BOARD_SETTINGS = 'BOARD_SETTINGS';
|
||||||
|
const BOARD_ACTIVITIES = 'BOARD_ACTIVITIES';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
ADMINISTRATION,
|
ADMINISTRATION,
|
||||||
|
@ -15,4 +16,5 @@ export default {
|
||||||
ADD_PROJECT,
|
ADD_PROJECT,
|
||||||
PROJECT_SETTINGS,
|
PROJECT_SETTINGS,
|
||||||
BOARD_SETTINGS,
|
BOARD_SETTINGS,
|
||||||
|
BOARD_ACTIVITIES,
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
|
|
||||||
import EntryActionTypes from '../constants/EntryActionTypes';
|
import EntryActionTypes from '../constants/EntryActionTypes';
|
||||||
|
|
||||||
|
const fetchActivitiesInCurrentBoard = () => ({
|
||||||
|
type: EntryActionTypes.ACTIVITIES_IN_CURRENT_BOARD_FETCH,
|
||||||
|
payload: {},
|
||||||
|
});
|
||||||
|
|
||||||
const fetchActivitiesInCurrentCard = () => ({
|
const fetchActivitiesInCurrentCard = () => ({
|
||||||
type: EntryActionTypes.ACTIVITIES_IN_CURRENT_CARD_FETCH,
|
type: EntryActionTypes.ACTIVITIES_IN_CURRENT_CARD_FETCH,
|
||||||
payload: {},
|
payload: {},
|
||||||
|
@ -18,6 +23,7 @@ const handleActivityCreate = (activity) => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
fetchActivitiesInCurrentBoard,
|
||||||
fetchActivitiesInCurrentCard,
|
fetchActivitiesInCurrentCard,
|
||||||
handleActivityCreate,
|
handleActivityCreate,
|
||||||
};
|
};
|
||||||
|
|
|
@ -47,6 +47,13 @@ const openBoardSettingsModal = (boardId) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const openBoardActivitiesModal = () => ({
|
||||||
|
type: EntryActionTypes.MODAL_OPEN,
|
||||||
|
payload: {
|
||||||
|
type: ModalTypes.BOARD_ACTIVITIES,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const closeModal = () => ({
|
const closeModal = () => ({
|
||||||
type: EntryActionTypes.MODAL_CLOSE,
|
type: EntryActionTypes.MODAL_CLOSE,
|
||||||
payload: {},
|
payload: {},
|
||||||
|
@ -58,5 +65,6 @@ export default {
|
||||||
openAddProjectModal,
|
openAddProjectModal,
|
||||||
openProjectSettingsModal,
|
openProjectSettingsModal,
|
||||||
openBoardSettingsModal,
|
openBoardSettingsModal,
|
||||||
|
openBoardActivitiesModal,
|
||||||
closeModal,
|
closeModal,
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,6 +59,7 @@ export default (initialClosableValue) => {
|
||||||
onClose: undefined,
|
onClose: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ClosableModal.Header = Modal.Header;
|
||||||
ClosableModal.Content = Modal.Content;
|
ClosableModal.Content = Modal.Content;
|
||||||
ClosableModal.Actions = Modal.Actions;
|
ClosableModal.Actions = Modal.Actions;
|
||||||
|
|
||||||
|
|
|
@ -152,12 +152,12 @@ export default {
|
||||||
time: 'الوقت',
|
time: 'الوقت',
|
||||||
title: 'العنوان',
|
title: 'العنوان',
|
||||||
userActions_title: 'إجراءات المستخدم',
|
userActions_title: 'إجراءات المستخدم',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> تمت إضافة هذه البطاقة إلى {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> تمت إضافة هذه البطاقة إلى {{list}}',
|
||||||
userLeftNewCommentToCard: '<0>{{user}}</0> ترك تعليق جديد «{{comment}}» إلى <2>{{card}}</2>',
|
userLeftNewCommentToCard: '<0>{{user}}</0> ترك تعليق جديد «{{comment}}» إلى <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> انتقل <2>{{card}}</2> من {{fromList}} إلى {{toList}}',
|
'<0>{{user}}</0> انتقل <2>{{card}}</2> من {{fromList}} إلى {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> نُقلت هذه البطاقة من {{fromList}} إلى {{toList}}</1>',
|
'<0>{{user}}</0> نُقلت هذه البطاقة من {{fromList}} إلى {{toList}}',
|
||||||
username: 'اسم المستخدم',
|
username: 'اسم المستخدم',
|
||||||
users: 'المستخدمين',
|
users: 'المستخدمين',
|
||||||
viewer: 'مشاهد',
|
viewer: 'مشاهد',
|
||||||
|
|
|
@ -153,13 +153,13 @@ export default {
|
||||||
time: 'Време',
|
time: 'Време',
|
||||||
title: 'Заглавие',
|
title: 'Заглавие',
|
||||||
userActions_title: 'Потребителски действия',
|
userActions_title: 'Потребителски действия',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> добави тази карта в {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> добави тази карта в {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> остави нов коментар «{{comment}}» в <2>{{card}}</2>',
|
'<0>{{user}}</0> остави нов коментар «{{comment}}» в <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> премести <2>{{card}}</2> от {{fromList}} към {{toList}}',
|
'<0>{{user}}</0> премести <2>{{card}}</2> от {{fromList}} към {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> премести тази карта от {{fromList}} към {{toList}}</1>',
|
'<0>{{user}}</0> премести тази карта от {{fromList}} към {{toList}}',
|
||||||
username: 'Потребителско име',
|
username: 'Потребителско име',
|
||||||
users: 'Потребители',
|
users: 'Потребители',
|
||||||
viewer: 'Зрител',
|
viewer: 'Зрител',
|
||||||
|
|
|
@ -276,13 +276,13 @@ export default {
|
||||||
unsavedChanges: 'Neuložené změny',
|
unsavedChanges: 'Neuložené změny',
|
||||||
uploadedImages: 'Nahrané obrázky',
|
uploadedImages: 'Nahrané obrázky',
|
||||||
userActions_title: 'Akce uživatele',
|
userActions_title: 'Akce uživatele',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> přidal kartu do {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> přidal kartu do {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> zanechal nový komentář «{{comment}}» k <2>{{card}}</2>',
|
'<0>{{user}}</0> zanechal nový komentář «{{comment}}» k <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> přesunul <2>{{card}}</2> z {{fromList}} do {{toList}}',
|
'<0>{{user}}</0> přesunul <2>{{card}}</2> z {{fromList}} do {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> přesunul tuto kartu z {{fromList}} do {{toList}}</1>',
|
'<0>{{user}}</0> přesunul tuto kartu z {{fromList}} do {{toList}}',
|
||||||
username: 'Uživatelské jméno',
|
username: 'Uživatelské jméno',
|
||||||
users: 'Uživatelé',
|
users: 'Uživatelé',
|
||||||
viewer: 'Prohlížeč',
|
viewer: 'Prohlížeč',
|
||||||
|
|
|
@ -154,13 +154,13 @@ export default {
|
||||||
time: 'Tid',
|
time: 'Tid',
|
||||||
title: 'Overskrift',
|
title: 'Overskrift',
|
||||||
userActions_title: 'Brugerhandlinger',
|
userActions_title: 'Brugerhandlinger',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> tilføjede kortet til {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> tilføjede kortet til {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> skrevet en ny kommentar «{{comment}}» på <2>{{card}}</2>',
|
'<0>{{user}}</0> skrevet en ny kommentar «{{comment}}» på <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> flyttede <2>{{card}}</2> fra {{fromList}} til {{toList}}',
|
'<0>{{user}}</0> flyttede <2>{{card}}</2> fra {{fromList}} til {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> flyttede kortet fra {{fromList}} til {{toList}}</1>',
|
'<0>{{user}}</0> flyttede kortet fra {{fromList}} til {{toList}}',
|
||||||
username: 'Brugernavn',
|
username: 'Brugernavn',
|
||||||
users: 'Brugere',
|
users: 'Brugere',
|
||||||
viewer: 'Læser',
|
viewer: 'Læser',
|
||||||
|
|
|
@ -296,13 +296,13 @@ export default {
|
||||||
unsavedChanges: 'Ungespeicherte Änderungen',
|
unsavedChanges: 'Ungespeicherte Änderungen',
|
||||||
uploadedImages: 'Hochgeladene Bilder',
|
uploadedImages: 'Hochgeladene Bilder',
|
||||||
userActions_title: 'Benutzeraktionen',
|
userActions_title: 'Benutzeraktionen',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> hat diese Karte hinzugefügt zu {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> hat diese Karte hinzugefügt zu {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> hat einen neuen Kommentar verfasst: «{{comment}}» in <2>{{card}}</2>',
|
'<0>{{user}}</0> hat einen neuen Kommentar verfasst: «{{comment}}» in <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> bewegte <2>{{card}}</2> von {{fromList}} nach {{toList}}',
|
'<0>{{user}}</0> bewegte <2>{{card}}</2> von {{fromList}} nach {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> bewegte diese Karte von {{fromList}} nach {{toList}}</1>',
|
'<0>{{user}}</0> bewegte diese Karte von {{fromList}} nach {{toList}}',
|
||||||
username: 'Benutzername',
|
username: 'Benutzername',
|
||||||
users: 'Benutzer',
|
users: 'Benutzer',
|
||||||
viewer: 'Betrachter',
|
viewer: 'Betrachter',
|
||||||
|
|
|
@ -286,22 +286,28 @@ export default {
|
||||||
unsavedChanges: 'Unsaved changes',
|
unsavedChanges: 'Unsaved changes',
|
||||||
uploadedImages: 'Uploaded images',
|
uploadedImages: 'Uploaded images',
|
||||||
userActions_title: 'User Actions',
|
userActions_title: 'User Actions',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> added this card to {{list}}</1>',
|
userAddedCardToList: '<0>{{user}}</0> added <2>{{card}}</2> to {{list}}',
|
||||||
userAddedUserToThisCard: '<0>{{actorUser}}</0><1> added {{addedUser}} to this card</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> added this card to {{list}}',
|
||||||
|
userAddedUserToCard: '<0>{{actorUser}}</0> added {{addedUser}} to <4>{{card}}</4>',
|
||||||
|
userAddedUserToThisCard: '<0>{{actorUser}}</0> added {{addedUser}} to this card',
|
||||||
userAddedYouToCard: '<0>{{user}}</0> added you to <2>{{card}}</2>',
|
userAddedYouToCard: '<0>{{user}}</0> added you to <2>{{card}}</2>',
|
||||||
userCompletedTaskOnThisCard: '<0>{{user}}</0><1> completed {{task}} on this card</1>',
|
userCompletedTaskOnCard: '<0>{{user}}</0> completed {{task}} on <4>{{card}}</4>',
|
||||||
userJoinedThisCard: `<0>{{user}}</0><1> joined this card</1>`,
|
userCompletedTaskOnThisCard: '<0>{{user}}</0> completed {{task}} on this card',
|
||||||
|
userJoinedCard: `<0>{{user}}</0> joined <2>{{card}}</2>`,
|
||||||
|
userJoinedThisCard: `<0>{{user}}</0> joined this card`,
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> left a new comment «{{comment}}» to <2>{{card}}</2>',
|
'<0>{{user}}</0> left a new comment «{{comment}}» to <2>{{card}}</2>',
|
||||||
userLeftThisCard: '<0>{{user}}</0><1> left this card</1>',
|
userLeftCard: '<0>{{user}}</0> left <2>{{card}}</2>',
|
||||||
userMarkedTaskIncompleteOnThisCard:
|
userLeftThisCard: '<0>{{user}}</0> left this card',
|
||||||
'<0>{{user}}</0><1> marked {{task}} incomplete on this card</1>',
|
userMarkedTaskIncompleteOnCard:
|
||||||
|
'<0>{{user}}</0> marked {{task}} incomplete on <4>{{card}}</4>',
|
||||||
|
userMarkedTaskIncompleteOnThisCard: '<0>{{user}}</0> marked {{task}} incomplete on this card',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> moved <2>{{card}}</2> from {{fromList}} to {{toList}}',
|
'<0>{{user}}</0> moved <2>{{card}}</2> from {{fromList}} to {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> moved this card from {{fromList}} to {{toList}}</1>',
|
'<0>{{user}}</0> moved this card from {{fromList}} to {{toList}}',
|
||||||
userRemovedUserFromThisCard:
|
userRemovedUserFromCard: '<0>{{actorUser}}</0> removed {{removedUser}} from <4>{{card}}</4>',
|
||||||
'<0>{{actorUser}}</0><1> removed {{removedUser}} from this card</1>',
|
userRemovedUserFromThisCard: '<0>{{actorUser}}</0> removed {{removedUser}} from this card',
|
||||||
username: 'Username',
|
username: 'Username',
|
||||||
users: 'Users',
|
users: 'Users',
|
||||||
viewer: 'Viewer',
|
viewer: 'Viewer',
|
||||||
|
|
|
@ -281,22 +281,28 @@ export default {
|
||||||
unsavedChanges: 'Unsaved changes',
|
unsavedChanges: 'Unsaved changes',
|
||||||
uploadedImages: 'Uploaded images',
|
uploadedImages: 'Uploaded images',
|
||||||
userActions_title: 'User Actions',
|
userActions_title: 'User Actions',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> added this card to {{list}}</1>',
|
userAddedCardToList: '<0>{{user}}</0> added <2>{{card}}</2> to {{list}}',
|
||||||
userAddedUserToThisCard: '<0>{{actorUser}}</0><1> added {{addedUser}} to this card</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> added this card to {{list}}',
|
||||||
|
userAddedUserToCard: '<0>{{actorUser}}</0> added {{addedUser}} to <4>{{card}}</4>',
|
||||||
|
userAddedUserToThisCard: '<0>{{actorUser}}</0> added {{addedUser}} to this card',
|
||||||
userAddedYouToCard: '<0>{{user}}</0> added you to <2>{{card}}</2>',
|
userAddedYouToCard: '<0>{{user}}</0> added you to <2>{{card}}</2>',
|
||||||
userCompletedTaskOnThisCard: '<0>{{user}}</0><1> completed {{task}} on this card</1>',
|
userCompletedTaskOnCard: '<0>{{user}}</0> completed {{task}} on <4>{{card}}</4>',
|
||||||
userJoinedThisCard: `<0>{{user}}</0><1> joined this card</1>`,
|
userCompletedTaskOnThisCard: '<0>{{user}}</0> completed {{task}} on this card',
|
||||||
|
userJoinedCard: `<0>{{user}}</0> joined <2>{{card}}</2>`,
|
||||||
|
userJoinedThisCard: `<0>{{user}}</0> joined this card`,
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> left a new comment «{{comment}}» to <2>{{card}}</2>',
|
'<0>{{user}}</0> left a new comment «{{comment}}» to <2>{{card}}</2>',
|
||||||
userLeftThisCard: '<0>{{user}}</0><1> left this card</1>',
|
userLeftCard: '<0>{{user}}</0> left <2>{{card}}</2>',
|
||||||
userMarkedTaskIncompleteOnThisCard:
|
userLeftThisCard: '<0>{{user}}</0> left this card',
|
||||||
'<0>{{user}}</0><1> marked {{task}} incomplete on this card</1>',
|
userMarkedTaskIncompleteOnCard:
|
||||||
|
'<0>{{user}}</0> marked {{task}} incomplete on <4>{{card}}</4>',
|
||||||
|
userMarkedTaskIncompleteOnThisCard: '<0>{{user}}</0> marked {{task}} incomplete on this card',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> moved <2>{{card}}</2> from {{fromList}} to {{toList}}',
|
'<0>{{user}}</0> moved <2>{{card}}</2> from {{fromList}} to {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> moved this card from {{fromList}} to {{toList}}</1>',
|
'<0>{{user}}</0> moved this card from {{fromList}} to {{toList}}',
|
||||||
userRemovedUserFromThisCard:
|
userRemovedUserFromCard: '<0>{{actorUser}}</0> removed {{removedUser}} from <4>{{card}}</4>',
|
||||||
'<0>{{actorUser}}</0><1> removed {{removedUser}} from this card</1>',
|
userRemovedUserFromThisCard: '<0>{{actorUser}}</0> removed {{removedUser}} from this card',
|
||||||
username: 'Username',
|
username: 'Username',
|
||||||
users: 'Users',
|
users: 'Users',
|
||||||
viewer: 'Viewer',
|
viewer: 'Viewer',
|
||||||
|
|
|
@ -117,13 +117,13 @@ export default {
|
||||||
time: 'Tiempo',
|
time: 'Tiempo',
|
||||||
title: 'Título',
|
title: 'Título',
|
||||||
userActions_title: 'Acciones de Usuario',
|
userActions_title: 'Acciones de Usuario',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> añadido a esta tarjeta en {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> añadido a esta tarjeta en {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> dejó un nuevo comentario «{{comment}}» en <2>{{card}}</2>',
|
'<0>{{user}}</0> dejó un nuevo comentario «{{comment}}» en <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> movió <2>{{card}}</2> de {{fromList}} a {{toList}}',
|
'<0>{{user}}</0> movió <2>{{card}}</2> de {{fromList}} a {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> movió esta tarjeta de {{fromList}} a {{toList}}</1>',
|
'<0>{{user}}</0> movió esta tarjeta de {{fromList}} a {{toList}}',
|
||||||
username: 'Nombre de usuario',
|
username: 'Nombre de usuario',
|
||||||
users: 'Usuarios',
|
users: 'Usuarios',
|
||||||
writeComment: 'Escribir un comentario...',
|
writeComment: 'Escribir un comentario...',
|
||||||
|
|
|
@ -153,13 +153,13 @@ export default {
|
||||||
time: 'زمان',
|
time: 'زمان',
|
||||||
title: 'عنوان',
|
title: 'عنوان',
|
||||||
userActions_title: 'اقدامات کاربر',
|
userActions_title: 'اقدامات کاربر',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> این کارت را به {{list}} اضافه کرد</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> این کارت را به {{list}} اضافه کرد',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> نظر جدید «{{comment}}» را به <2>{{card}}</2> اضافه کرد',
|
'<0>{{user}}</0> نظر جدید «{{comment}}» را به <2>{{card}}</2> اضافه کرد',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> <2>{{card}}</2> را از {{fromList}} به {{toList}} منتقل کرد',
|
'<0>{{user}}</0> <2>{{card}}</2> را از {{fromList}} به {{toList}} منتقل کرد',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> این کارت را از {{fromList}} به {{toList}} منتقل کرد</1>',
|
'<0>{{user}}</0> این کارت را از {{fromList}} به {{toList}} منتقل کرد',
|
||||||
username: 'نام کاربری',
|
username: 'نام کاربری',
|
||||||
users: 'کاربران',
|
users: 'کاربران',
|
||||||
viewer: 'بیننده',
|
viewer: 'بیننده',
|
||||||
|
|
|
@ -153,13 +153,13 @@ export default {
|
||||||
time: 'Temps',
|
time: 'Temps',
|
||||||
title: 'Titre',
|
title: 'Titre',
|
||||||
userActions_title: "Actions de l'utilisateur",
|
userActions_title: "Actions de l'utilisateur",
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> a ajouté cette carte à {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> a ajouté cette carte à {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> a laissé un nouveau commentaire {{comment}} à <2>{{card}}</2>',
|
'<0>{{user}}</0> a laissé un nouveau commentaire {{comment}} à <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> a déplacé <2>{{card}}</2> de {{fromList}} vers {{toList}}',
|
'<0>{{user}}</0> a déplacé <2>{{card}}</2> de {{fromList}} vers {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> a déplacé cette carte de {{fromList}} vers {{toList}}</1>',
|
'<0>{{user}}</0> a déplacé cette carte de {{fromList}} vers {{toList}}',
|
||||||
username: "Nom d'utilisateur",
|
username: "Nom d'utilisateur",
|
||||||
users: 'Utilisateurs',
|
users: 'Utilisateurs',
|
||||||
viewer: 'Spectateur',
|
viewer: 'Spectateur',
|
||||||
|
|
|
@ -151,14 +151,13 @@ export default {
|
||||||
time: 'Idő',
|
time: 'Idő',
|
||||||
title: 'Cím',
|
title: 'Cím',
|
||||||
userActions_title: 'Felhasználói műveletek',
|
userActions_title: 'Felhasználói műveletek',
|
||||||
userAddedThisCardToList:
|
userAddedThisCardToList: '<0>{{user}}</0> hozzáadta ezt a kártyát a következőhöz: {{list}}',
|
||||||
'<0>{{user}}</0><1> hozzáadta ezt a kártyát a következőhöz: {{list}}</1>',
|
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> új kommentet hagyott itt: «{{comment}}» a következő kártyán: <2>{{card}}</2>',
|
'<0>{{user}}</0> új kommentet hagyott itt: «{{comment}}» a következő kártyán: <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> áthelyezte ezt a kártyát innen: {{fromList}} ide: {{toList}}',
|
'<0>{{user}}</0> áthelyezte ezt a kártyát innen: {{fromList}} ide: {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> áthelyezte ezt a kártyát innen: {{fromList}} ide: {{toList}}</1>',
|
'<0>{{user}}</0> áthelyezte ezt a kártyát innen: {{fromList}} ide: {{toList}}',
|
||||||
username: 'Felhasználónév',
|
username: 'Felhasználónév',
|
||||||
users: 'Felhasználók',
|
users: 'Felhasználók',
|
||||||
viewer: 'Néző',
|
viewer: 'Néző',
|
||||||
|
|
|
@ -147,12 +147,12 @@ export default {
|
||||||
time: 'Waktu',
|
time: 'Waktu',
|
||||||
title: 'Judul',
|
title: 'Judul',
|
||||||
userActions_title: 'Aksi Pengguna',
|
userActions_title: 'Aksi Pengguna',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> menambahkan kartu ini ke {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> menambahkan kartu ini ke {{list}}',
|
||||||
userLeftNewCommentToCard: '<0>{{user}}</0> mengomentari «{{comment}}» di <2>{{card}}</2>',
|
userLeftNewCommentToCard: '<0>{{user}}</0> mengomentari «{{comment}}» di <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> memindahkan <2>{{card}}</2> dari {{fromList}} ke {{toList}}',
|
'<0>{{user}}</0> memindahkan <2>{{card}}</2> dari {{fromList}} ke {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> memindahkan kartu ini dari {{fromList}} ke {{toList}}</1>',
|
'<0>{{user}}</0> memindahkan kartu ini dari {{fromList}} ke {{toList}}',
|
||||||
username: 'Username',
|
username: 'Username',
|
||||||
users: 'Pengguna',
|
users: 'Pengguna',
|
||||||
viewer: 'Penglihat',
|
viewer: 'Penglihat',
|
||||||
|
|
|
@ -284,13 +284,13 @@ export default {
|
||||||
unsavedChanges: 'Modifiche non salvate',
|
unsavedChanges: 'Modifiche non salvate',
|
||||||
uploadedImages: 'Immagini caricate',
|
uploadedImages: 'Immagini caricate',
|
||||||
userActions_title: 'Azioni utente',
|
userActions_title: 'Azioni utente',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> ha aggiunto questa scheda a {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> ha aggiunto questa scheda a {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> ha lasciato un commento «{{comment}}» a <2>{{card}}</2>',
|
'<0>{{user}}</0> ha lasciato un commento «{{comment}}» a <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> ha spostato <2>{{card}}</2> da {{fromList}} a {{toList}}',
|
'<0>{{user}}</0> ha spostato <2>{{card}}</2> da {{fromList}} a {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> ha spostato questa scheda da {{fromList}} a {{toList}}</1>',
|
'<0>{{user}}</0> ha spostato questa scheda da {{fromList}} a {{toList}}',
|
||||||
username: 'Username',
|
username: 'Username',
|
||||||
users: 'Utenti',
|
users: 'Utenti',
|
||||||
viewer: 'Visualizzatore',
|
viewer: 'Visualizzatore',
|
||||||
|
|
|
@ -146,13 +146,13 @@ export default {
|
||||||
time: '時間',
|
time: '時間',
|
||||||
title: 'タイトル',
|
title: 'タイトル',
|
||||||
userActions_title: 'ユーザーのアクション',
|
userActions_title: 'ユーザーのアクション',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0> 様が <1>{{list}} をこのカードに追加しました</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> 様が {{list}} をこのカードに追加しました',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> 様が <2>{{card}}</2> に新しいコメント «{{comment}}» を残しました',
|
'<0>{{user}}</0> 様が <2>{{card}}</2> に新しいコメント «{{comment}}» を残しました',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> 様が <2>{{card}}</2> を {{fromList}} から {{toList}} に移動しました',
|
'<0>{{user}}</0> 様が <2>{{card}}</2> を {{fromList}} から {{toList}} に移動しました',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> 様がこのカードを {{fromList}} から {{toList}} に移動しました</1>',
|
'<0>{{user}}</0> 様がこのカードを {{fromList}} から {{toList}} に移動しました',
|
||||||
username: 'ユーザー名',
|
username: 'ユーザー名',
|
||||||
users: 'ユーザー',
|
users: 'ユーザー',
|
||||||
viewer: 'ビューア',
|
viewer: 'ビューア',
|
||||||
|
|
|
@ -151,13 +151,13 @@ export default {
|
||||||
time: '시간',
|
time: '시간',
|
||||||
title: '제목',
|
title: '제목',
|
||||||
userActions_title: '사용자 작업',
|
userActions_title: '사용자 작업',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1>님이 이 카드를 {{list}}에 추가했습니다</1>',
|
userAddedThisCardToList: '<0>{{user}}</0>님이 이 카드를 {{list}}에 추가했습니다',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0>님이 <2>{{card}}</2>에 새 댓글 «{{comment}}»을 남겼습니다',
|
'<0>{{user}}</0>님이 <2>{{card}}</2>에 새 댓글 «{{comment}}»을 남겼습니다',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0>님이 <2>{{card}}</2>를 {{fromList}}에서 {{toList}}로 이동했습니다',
|
'<0>{{user}}</0>님이 <2>{{card}}</2>를 {{fromList}}에서 {{toList}}로 이동했습니다',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> 님이 {{fromList}}에서 {{toList}}로 이 카드를 옮겼습니다</1>',
|
'<0>{{user}}</0> 님이 {{fromList}}에서 {{toList}}로 이 카드를 옮겼습니다',
|
||||||
username: '사용자 이름',
|
username: '사용자 이름',
|
||||||
users: '사용자들',
|
users: '사용자들',
|
||||||
viewer: '뷰어',
|
viewer: '뷰어',
|
||||||
|
|
|
@ -147,13 +147,13 @@ export default {
|
||||||
time: 'Tijd',
|
time: 'Tijd',
|
||||||
title: 'Titel',
|
title: 'Titel',
|
||||||
userActions_title: 'Gebruikersacties',
|
userActions_title: 'Gebruikersacties',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> heeft deze kaart toegevoegd aan {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> heeft deze kaart toegevoegd aan {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> heeft een nieuwe opmerking achtergelaten «{{comment}}» bij <2>{{card}}</2>',
|
'<0>{{user}}</0> heeft een nieuwe opmerking achtergelaten «{{comment}}» bij <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> heeft <2>{{card}}</2> verplaatst van {{fromList}} naar {{toList}}',
|
'<0>{{user}}</0> heeft <2>{{card}}</2> verplaatst van {{fromList}} naar {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> heeft deze kaart verplaatst van {{fromList}} naar {{toList}}</1>',
|
'<0>{{user}}</0> heeft deze kaart verplaatst van {{fromList}} naar {{toList}}',
|
||||||
username: 'Gebruikersnaam',
|
username: 'Gebruikersnaam',
|
||||||
users: 'Gebruikers',
|
users: 'Gebruikers',
|
||||||
viewer: 'Kijker',
|
viewer: 'Kijker',
|
||||||
|
|
|
@ -148,13 +148,13 @@ export default {
|
||||||
time: 'Czas',
|
time: 'Czas',
|
||||||
title: 'Tytuł',
|
title: 'Tytuł',
|
||||||
userActions_title: 'Akcje użytkownika',
|
userActions_title: 'Akcje użytkownika',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> dodał tę kartę w {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> dodał tę kartę w {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> zamieścił nowy komentarz «{{comment}}» w <2>{{card}}</2>',
|
'<0>{{user}}</0> zamieścił nowy komentarz «{{comment}}» w <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> przeniósł <2>{{card}}</2> z {{fromList}} do {{toList}}',
|
'<0>{{user}}</0> przeniósł <2>{{card}}</2> z {{fromList}} do {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> przeniósł tę kartę z {{fromList}} do {{toList}}</1>',
|
'<0>{{user}}</0> przeniósł tę kartę z {{fromList}} do {{toList}}',
|
||||||
username: 'Nazwa Użytkownika',
|
username: 'Nazwa Użytkownika',
|
||||||
users: 'Użytkownicy',
|
users: 'Użytkownicy',
|
||||||
viewer: 'Odwiedzający',
|
viewer: 'Odwiedzający',
|
||||||
|
|
|
@ -147,13 +147,13 @@ export default {
|
||||||
time: 'Tempo',
|
time: 'Tempo',
|
||||||
title: 'Título',
|
title: 'Título',
|
||||||
userActions_title: 'Ações do Usuário',
|
userActions_title: 'Ações do Usuário',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> adicionou este cartão a {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> adicionou este cartão a {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> deixou um novo comentário «{{comment}}» em <2>{{card}}</2>',
|
'<0>{{user}}</0> deixou um novo comentário «{{comment}}» em <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> moveu <2>{{card}}</2> de {{fromList}} para {{toList}}',
|
'<0>{{user}}</0> moveu <2>{{card}}</2> de {{fromList}} para {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> moveu este cartão de {{fromList}} para {{toList}}</1>',
|
'<0>{{user}}</0> moveu este cartão de {{fromList}} para {{toList}}',
|
||||||
username: 'Nome de usuário',
|
username: 'Nome de usuário',
|
||||||
users: 'Usuários',
|
users: 'Usuários',
|
||||||
viewer: 'Visualizador',
|
viewer: 'Visualizador',
|
||||||
|
|
|
@ -147,13 +147,13 @@ export default {
|
||||||
time: 'Timp',
|
time: 'Timp',
|
||||||
title: 'Titlu',
|
title: 'Titlu',
|
||||||
userActions_title: 'Acțiunile utilizatorului',
|
userActions_title: 'Acțiunile utilizatorului',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> a adăugat acest card în {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> a adăugat acest card în {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> a lăsat un nou comentariu «{{comment}}» în <2>{{card}}</2>',
|
'<0>{{user}}</0> a lăsat un nou comentariu «{{comment}}» în <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> a mutat <2>{{card}}</2> din {{fromList}} în {{toList}}',
|
'<0>{{user}}</0> a mutat <2>{{card}}</2> din {{fromList}} în {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> a mutat aceast card din {{fromList}} în {{toList}}</1>',
|
'<0>{{user}}</0> a mutat aceast card din {{fromList}} în {{toList}}',
|
||||||
username: 'Nume utilizator',
|
username: 'Nume utilizator',
|
||||||
users: 'Utilizatori',
|
users: 'Utilizatori',
|
||||||
viewer: 'Vizualizator',
|
viewer: 'Vizualizator',
|
||||||
|
|
|
@ -284,13 +284,13 @@ export default {
|
||||||
unsavedChanges: 'Несохранённые изменения',
|
unsavedChanges: 'Несохранённые изменения',
|
||||||
uploadedImages: 'Загруженные изображения',
|
uploadedImages: 'Загруженные изображения',
|
||||||
userActions_title: 'Действия с пользователем',
|
userActions_title: 'Действия с пользователем',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> добавил(а) эту карточку в {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> добавил(а) эту карточку в {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> оставил(а) комментарий «{{comment}}» к <2>{{card}}</2>',
|
'<0>{{user}}</0> оставил(а) комментарий «{{comment}}» к <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> переместил(а) <2>{{card}}</2> из {{fromList}} в {{toList}}',
|
'<0>{{user}}</0> переместил(а) <2>{{card}}</2> из {{fromList}} в {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> переместил(а) эту карточку из {{fromList}} в {{toList}}</1>',
|
'<0>{{user}}</0> переместил(а) эту карточку из {{fromList}} в {{toList}}',
|
||||||
username: 'Имя пользователя',
|
username: 'Имя пользователя',
|
||||||
users: 'Пользователи',
|
users: 'Пользователи',
|
||||||
viewer: 'Читатель',
|
viewer: 'Читатель',
|
||||||
|
|
|
@ -132,13 +132,13 @@ export default {
|
||||||
time: 'Čas',
|
time: 'Čas',
|
||||||
title: 'Názov',
|
title: 'Názov',
|
||||||
userActions_title: 'Akcie na používateľovi',
|
userActions_title: 'Akcie na používateľovi',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> pridal kartu do {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> pridal kartu do {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> zanechal nový komentár «{{comment}}» k <2>{{card}}</2>',
|
'<0>{{user}}</0> zanechal nový komentár «{{comment}}» k <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> presunul <2>{{card}}</2> z {{fromList}} do {{toList}}',
|
'<0>{{user}}</0> presunul <2>{{card}}</2> z {{fromList}} do {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> presunul túto kartu z {{fromList}} do {{toList}}</1>',
|
'<0>{{user}}</0> presunul túto kartu z {{fromList}} do {{toList}}',
|
||||||
username: 'Používateľské meno',
|
username: 'Používateľské meno',
|
||||||
users: 'Používatelia',
|
users: 'Používatelia',
|
||||||
writeComment: 'Napísať komentár...',
|
writeComment: 'Napísať komentár...',
|
||||||
|
|
|
@ -152,13 +152,13 @@ export default {
|
||||||
time: 'Време',
|
time: 'Време',
|
||||||
title: 'Наслов',
|
title: 'Наслов',
|
||||||
userActions_title: 'Корисничке радње',
|
userActions_title: 'Корисничке радње',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> је додао ову картицу на {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> је додао ову картицу на {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> је оставио нови коментар «{{comment}}» у <2>{{card}}</2>',
|
'<0>{{user}}</0> је оставио нови коментар «{{comment}}» у <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> је преместио <2>{{card}}</2> са {{fromList}} у {{toList}}',
|
'<0>{{user}}</0> је преместио <2>{{card}}</2> са {{fromList}} у {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> је преместио ову картицу са {{fromList}} на {{toList}}</1>',
|
'<0>{{user}}</0> је преместио ову картицу са {{fromList}} на {{toList}}',
|
||||||
username: 'Корисничко име',
|
username: 'Корисничко име',
|
||||||
users: 'Корисници',
|
users: 'Корисници',
|
||||||
viewer: 'Прегледач',
|
viewer: 'Прегледач',
|
||||||
|
|
|
@ -152,13 +152,13 @@ export default {
|
||||||
time: 'Vreme',
|
time: 'Vreme',
|
||||||
title: 'Naslov',
|
title: 'Naslov',
|
||||||
userActions_title: 'Korisničke radnje',
|
userActions_title: 'Korisničke radnje',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> je dodao ovu karticu na {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> je dodao ovu karticu na {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> je ostavio novi komentar «{{comment}}» u <2>{{card}}</2>',
|
'<0>{{user}}</0> je ostavio novi komentar «{{comment}}» u <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> je premestio <2>{{card}}</2> sa {{fromList}} u {{toList}}',
|
'<0>{{user}}</0> je premestio <2>{{card}}</2> sa {{fromList}} u {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> je premestio ovu karticu sa {{fromList}} na {{toList}}</1>',
|
'<0>{{user}}</0> je premestio ovu karticu sa {{fromList}} na {{toList}}',
|
||||||
username: 'Korisničko ime',
|
username: 'Korisničko ime',
|
||||||
users: 'Korisnici',
|
users: 'Korisnici',
|
||||||
viewer: 'Pregledač',
|
viewer: 'Pregledač',
|
||||||
|
|
|
@ -133,13 +133,13 @@ export default {
|
||||||
time: 'Tid',
|
time: 'Tid',
|
||||||
title: 'Titel',
|
title: 'Titel',
|
||||||
userActions_title: 'Användaråtgärder',
|
userActions_title: 'Användaråtgärder',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> lade till detta kort i {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> lade till detta kort i {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> lämnade en ny kommentar «{{comment}}» på <2>{{card}}</2>',
|
'<0>{{user}}</0> lämnade en ny kommentar «{{comment}}» på <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> flyttade <2>{{card}}</2> från {{fromList}} till {{toList}}',
|
'<0>{{user}}</0> flyttade <2>{{card}}</2> från {{fromList}} till {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> flyttade detta kort från {{fromList}} till {{toList}}</1>',
|
'<0>{{user}}</0> flyttade detta kort från {{fromList}} till {{toList}}',
|
||||||
username: 'Användarnamn',
|
username: 'Användarnamn',
|
||||||
users: 'Användare',
|
users: 'Användare',
|
||||||
writeComment: 'Skriv en kommentar...',
|
writeComment: 'Skriv en kommentar...',
|
||||||
|
|
|
@ -134,13 +134,13 @@ export default {
|
||||||
time: 'zaman',
|
time: 'zaman',
|
||||||
title: 'başlık',
|
title: 'başlık',
|
||||||
userActions_title: 'Kullanıcı İşlemleri',
|
userActions_title: 'Kullanıcı İşlemleri',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> bu kartı {{list}</1> listesine ekledi',
|
userAddedThisCardToList: '<0>{{user}}</0> bu kartı {{list}} listesine ekledi',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> yeni bir yorum yazdı: <2>{{card}</2> kartına «{{comment}}»',
|
'<0>{{user}}</0> yeni bir yorum yazdı: <2>{{card}</2> kartına «{{comment}}»',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0>, <2>{{card}></2> kartını {{fromList}} listesinden {{toList}} listesine taşıdı',
|
'<0>{{user}}</0>, <2>{{card}></2> kartını {{fromList}} listesinden {{toList}} listesine taşıdı',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> bu kartı {{fromList}} konumundan {{toList}}</1> konumuna taşıdı',
|
'<0>{{user}}</0> bu kartı {{fromList}} konumundan {{toList}} konumuna taşıdı',
|
||||||
username: 'kullanıcı adı',
|
username: 'kullanıcı adı',
|
||||||
users: 'kullanıcı',
|
users: 'kullanıcı',
|
||||||
writeComment: 'Yorum yazın...',
|
writeComment: 'Yorum yazın...',
|
||||||
|
|
|
@ -281,13 +281,13 @@ export default {
|
||||||
unsavedChanges: 'Незбережені зміни',
|
unsavedChanges: 'Незбережені зміни',
|
||||||
uploadedImages: 'Завантажені зображення',
|
uploadedImages: 'Завантажені зображення',
|
||||||
userActions_title: 'Дії користувача',
|
userActions_title: 'Дії користувача',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> додав(ла) цю картку до {{list}}</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> додав(ла) цю картку до {{list}}',
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> залишив(ла) новий коментар «{{comment}}» до <2>{{card}}</2>',
|
'<0>{{user}}</0> залишив(ла) новий коментар «{{comment}}» до <2>{{card}}</2>',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> перемістив(ла) <2>{{card}}</2> з {{fromList}} в {{toList}}',
|
'<0>{{user}}</0> перемістив(ла) <2>{{card}}</2> з {{fromList}} в {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
'<0>{{user}}</0><1> перемістив(ла) цю картку з {{fromList}} в {{toList}}</1>',
|
'<0>{{user}}</0> перемістив(ла) цю картку з {{fromList}} в {{toList}}',
|
||||||
username: "Ім'я користувача",
|
username: "Ім'я користувача",
|
||||||
users: 'Користувачі',
|
users: 'Користувачі',
|
||||||
viewer: 'Переглядач',
|
viewer: 'Переглядач',
|
||||||
|
|
|
@ -130,13 +130,13 @@ export default {
|
||||||
time: 'Vaqt',
|
time: 'Vaqt',
|
||||||
title: 'Sarlavha',
|
title: 'Sarlavha',
|
||||||
userActions_title: 'Foydalanuvchi Amallari',
|
userActions_title: 'Foydalanuvchi Amallari',
|
||||||
userAddedThisCardToList: "<1>Ushbu kartani {{list}} ga</1><0>{{user}}</0> qo'shdi",
|
userAddedThisCardToList: "Ushbu kartani {{list}} ga<0>{{user}}</0> qo'shdi",
|
||||||
userLeftNewCommentToCard:
|
userLeftNewCommentToCard:
|
||||||
'<0>{{user}}</0> <2>{{card}}</2> ga yangi izoh qoldirdi «{{comment}}»',
|
'<0>{{user}}</0> <2>{{card}}</2> ga yangi izoh qoldirdi «{{comment}}»',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
"<0>{{user}}</0> <2>{{card}}</2> ni {{fromList}} dan {{toList}} ga ko'chirdi",
|
"<0>{{user}}</0> <2>{{card}}</2> ni {{fromList}} dan {{toList}} ga ko'chirdi",
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList:
|
||||||
"<0>{{user}}</0><1> ushbu kartani {{fromList}} dan {{toList}}</1> ga ko'chirdi",
|
"<0>{{user}}</0> ushbu kartani {{fromList}} dan {{toList}} ga ko'chirdi",
|
||||||
username: 'Foydalanuvchi nomi',
|
username: 'Foydalanuvchi nomi',
|
||||||
users: 'Foydalanuvchilar',
|
users: 'Foydalanuvchilar',
|
||||||
writeComment: 'Izoh yozish...',
|
writeComment: 'Izoh yozish...',
|
||||||
|
|
|
@ -143,12 +143,11 @@ export default {
|
||||||
time: '时间',
|
time: '时间',
|
||||||
title: '标题',
|
title: '标题',
|
||||||
userActions_title: '用户操作',
|
userActions_title: '用户操作',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> 向列表 {{list}} 添加了该卡片</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> 向列表 {{list}} 添加了该卡片',
|
||||||
userLeftNewCommentToCard: '<0>{{user}}</0> 给 {{card}} 添加了一个新评论 «{{comment}}»',
|
userLeftNewCommentToCard: '<0>{{user}}</0> 给 <2>{{card}}</2> 添加了一个新评论 «{{comment}}»',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> 将卡片 <2>{{card}}</2> 从 {{fromList}} 移动到 {{toList}}',
|
'<0>{{user}}</0> 将卡片 <2>{{card}}</2> 从 {{fromList}} 移动到 {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList: '<0>{{user}}</0> 将该卡片从 {{fromList}} 移动到 {{toList}}',
|
||||||
'<0>{{user}}</0><1> 将该卡片从 {{fromList}} 移动到 {{toList}}</1>',
|
|
||||||
username: '用户名',
|
username: '用户名',
|
||||||
users: '用户',
|
users: '用户',
|
||||||
viewer: '视图',
|
viewer: '视图',
|
||||||
|
|
|
@ -143,12 +143,12 @@ export default {
|
||||||
time: '時間',
|
time: '時間',
|
||||||
title: '標題',
|
title: '標題',
|
||||||
userActions_title: '使用者操作',
|
userActions_title: '使用者操作',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0><1> 向列表 {{list}} 添加了該卡片</1>',
|
userAddedThisCardToList: '<0>{{user}}</0> 向列表 {{list}} 添加了該卡片',
|
||||||
userLeftNewCommentToCard: '<0>{{user}}</0> 給 {{card}} 添加了一條新評論 「{{comment}}」',
|
userLeftNewCommentToCard:
|
||||||
|
'<0>{{user}}</0> 給 <2>{{card}}</2> 添加了一條新評論 「{{comment}}」',
|
||||||
userMovedCardFromListToList:
|
userMovedCardFromListToList:
|
||||||
'<0>{{user}}</0> 將卡片 <2>{{card}}</2> 從 {{fromList}} 移動到 {{toList}}',
|
'<0>{{user}}</0> 將卡片 <2>{{card}}</2> 從 {{fromList}} 移動到 {{toList}}',
|
||||||
userMovedThisCardFromListToList:
|
userMovedThisCardFromListToList: '<0>{{user}}</0> 將該卡片從 {{fromList}} 移動到 {{toList}}',
|
||||||
'<0>{{user}}</0><1> 將該卡片從 {{fromList}} 移動到 {{toList}}</1>',
|
|
||||||
username: '使用者名稱',
|
username: '使用者名稱',
|
||||||
users: '使用者',
|
users: '使用者',
|
||||||
viewer: '檢視',
|
viewer: '檢視',
|
||||||
|
|
|
@ -18,6 +18,11 @@ export default class extends BaseModel {
|
||||||
createdAt: attr({
|
createdAt: attr({
|
||||||
getDefault: () => new Date(),
|
getDefault: () => new Date(),
|
||||||
}),
|
}),
|
||||||
|
boardId: fk({
|
||||||
|
to: 'Board',
|
||||||
|
as: 'board',
|
||||||
|
relatedName: 'activities',
|
||||||
|
}),
|
||||||
cardId: fk({
|
cardId: fk({
|
||||||
to: 'Card',
|
to: 'Card',
|
||||||
as: 'card',
|
as: 'card',
|
||||||
|
@ -37,7 +42,8 @@ export default class extends BaseModel {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ActionTypes.LIST_CARDS_MOVE__SUCCESS:
|
case ActionTypes.LIST_CARDS_MOVE__SUCCESS:
|
||||||
case ActionTypes.ACTIVITIES_FETCH__SUCCESS:
|
case ActionTypes.ACTIVITIES_IN_BOARD_FETCH__SUCCESS:
|
||||||
|
case ActionTypes.ACTIVITIES_IN_CARD_FETCH__SUCCESS:
|
||||||
payload.activities.forEach((activity) => {
|
payload.activities.forEach((activity) => {
|
||||||
Activity.upsert(activity);
|
Activity.upsert(activity);
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,6 +9,7 @@ import BaseModel from './BaseModel';
|
||||||
import buildSearchParts from '../utils/build-search-parts';
|
import buildSearchParts from '../utils/build-search-parts';
|
||||||
import { isListFinite } from '../utils/record-helpers';
|
import { isListFinite } from '../utils/record-helpers';
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
import Config from '../constants/Config';
|
||||||
import { BoardContexts, BoardViews } from '../constants/Enums';
|
import { BoardContexts, BoardViews } from '../constants/Enums';
|
||||||
|
|
||||||
const prepareFetchedBoard = (board) => ({
|
const prepareFetchedBoard = (board) => ({
|
||||||
|
@ -39,6 +40,15 @@ export default class extends BaseModel {
|
||||||
isFetching: attr({
|
isFetching: attr({
|
||||||
getDefault: () => null,
|
getDefault: () => null,
|
||||||
}),
|
}),
|
||||||
|
lastActivityId: attr({
|
||||||
|
getDefault: () => null,
|
||||||
|
}),
|
||||||
|
isActivitiesFetching: attr({
|
||||||
|
getDefault: () => false,
|
||||||
|
}),
|
||||||
|
isAllActivitiesFetched: attr({
|
||||||
|
getDefault: () => null,
|
||||||
|
}),
|
||||||
projectId: fk({
|
projectId: fk({
|
||||||
to: 'Project',
|
to: 'Project',
|
||||||
as: 'project',
|
as: 'project',
|
||||||
|
@ -241,6 +251,22 @@ export default class extends BaseModel {
|
||||||
case ActionTypes.LABEL_FROM_BOARD_FILTER_REMOVE:
|
case ActionTypes.LABEL_FROM_BOARD_FILTER_REMOVE:
|
||||||
Board.withId(payload.boardId).filterLabels.remove(payload.id);
|
Board.withId(payload.boardId).filterLabels.remove(payload.id);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ActionTypes.ACTIVITIES_IN_BOARD_FETCH:
|
||||||
|
Board.withId(payload.boardId).update({
|
||||||
|
isActivitiesFetching: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ActionTypes.ACTIVITIES_IN_BOARD_FETCH__SUCCESS:
|
||||||
|
Board.withId(payload.boardId).update({
|
||||||
|
isActivitiesFetching: false,
|
||||||
|
isAllActivitiesFetched: payload.activities.length < Config.ACTIVITIES_LIMIT,
|
||||||
|
...(payload.activities.length > 0 && {
|
||||||
|
lastActivityId: payload.activities[payload.activities.length - 1].id,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
@ -266,6 +292,10 @@ export default class extends BaseModel {
|
||||||
return this.customFieldGroups.orderBy(['position', 'id.length', 'id']);
|
return this.customFieldGroups.orderBy(['position', 'id.length', 'id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getActivitiesQuerySet() {
|
||||||
|
return this.activities.orderBy(['id.length', 'id'], ['desc', 'desc']);
|
||||||
|
}
|
||||||
|
|
||||||
getUnreadNotificationsQuerySet() {
|
getUnreadNotificationsQuerySet() {
|
||||||
return this.notifications.filter({
|
return this.notifications.filter({
|
||||||
isRead: false,
|
isRead: false,
|
||||||
|
@ -347,6 +377,30 @@ export default class extends BaseModel {
|
||||||
return cardModels;
|
return cardModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getActivitiesModelArray() {
|
||||||
|
if (this.isAllActivitiesFetched === null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const activityModels = this.getActivitiesQuerySet().toModelArray();
|
||||||
|
|
||||||
|
if (this.lastActivityId && this.isAllActivitiesFetched === false) {
|
||||||
|
return activityModels.filter((activityModel) => {
|
||||||
|
if (activityModel.id.length > this.lastActivityId.length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activityModel.id.length < this.lastActivityId.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return activityModel.id >= this.lastActivityId;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return activityModels;
|
||||||
|
}
|
||||||
|
|
||||||
hasMembershipWithUserId(userId) {
|
hasMembershipWithUserId(userId) {
|
||||||
return this.memberships
|
return this.memberships
|
||||||
.filter({
|
.filter({
|
||||||
|
|
|
@ -402,13 +402,13 @@ export default class extends BaseModel {
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ActionTypes.ACTIVITIES_FETCH:
|
case ActionTypes.ACTIVITIES_IN_CARD_FETCH:
|
||||||
Card.withId(payload.cardId).update({
|
Card.withId(payload.cardId).update({
|
||||||
isActivitiesFetching: true,
|
isActivitiesFetching: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ActionTypes.ACTIVITIES_FETCH__SUCCESS:
|
case ActionTypes.ACTIVITIES_IN_CARD_FETCH__SUCCESS:
|
||||||
Card.withId(payload.cardId).update({
|
Card.withId(payload.cardId).update({
|
||||||
isActivitiesFetching: false,
|
isActivitiesFetching: false,
|
||||||
isAllActivitiesFetched: payload.activities.length < Config.ACTIVITIES_LIMIT,
|
isAllActivitiesFetched: payload.activities.length < Config.ACTIVITIES_LIMIT,
|
||||||
|
@ -607,7 +607,6 @@ export default class extends BaseModel {
|
||||||
|
|
||||||
this.customFieldValues.delete();
|
this.customFieldValues.delete();
|
||||||
this.comments.delete();
|
this.comments.delete();
|
||||||
this.activities.delete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteWithClearable() {
|
deleteWithClearable() {
|
||||||
|
|
|
@ -295,7 +295,8 @@ export default class extends BaseModel {
|
||||||
case ActionTypes.CARD_CREATE_HANDLE:
|
case ActionTypes.CARD_CREATE_HANDLE:
|
||||||
case ActionTypes.COMMENTS_FETCH__SUCCESS:
|
case ActionTypes.COMMENTS_FETCH__SUCCESS:
|
||||||
case ActionTypes.COMMENT_CREATE_HANDLE:
|
case ActionTypes.COMMENT_CREATE_HANDLE:
|
||||||
case ActionTypes.ACTIVITIES_FETCH__SUCCESS:
|
case ActionTypes.ACTIVITIES_IN_BOARD_FETCH__SUCCESS:
|
||||||
|
case ActionTypes.ACTIVITIES_IN_CARD_FETCH__SUCCESS:
|
||||||
case ActionTypes.NOTIFICATION_CREATE_HANDLE:
|
case ActionTypes.NOTIFICATION_CREATE_HANDLE:
|
||||||
payload.users.forEach((user) => {
|
payload.users.forEach((user) => {
|
||||||
User.upsert(user);
|
User.upsert(user);
|
||||||
|
|
|
@ -10,10 +10,10 @@ import selectors from '../../../selectors';
|
||||||
import actions from '../../../actions';
|
import actions from '../../../actions';
|
||||||
import api from '../../../api';
|
import api from '../../../api';
|
||||||
|
|
||||||
export function* fetchActivities(cardId) {
|
export function* fetchActivitiesInBoard(boardId) {
|
||||||
const { lastActivityId } = yield select(selectors.selectCardById, cardId);
|
const { lastActivityId } = yield select(selectors.selectBoardById, boardId);
|
||||||
|
|
||||||
yield put(actions.fetchActivities(cardId));
|
yield put(actions.fetchActivitiesInBoard(boardId));
|
||||||
|
|
||||||
let activities;
|
let activities;
|
||||||
let users;
|
let users;
|
||||||
|
@ -22,21 +22,50 @@ export function* fetchActivities(cardId) {
|
||||||
({
|
({
|
||||||
items: activities,
|
items: activities,
|
||||||
included: { users },
|
included: { users },
|
||||||
} = yield call(request, api.getActivities, cardId, {
|
} = yield call(request, api.getActivitiesInBoard, boardId, {
|
||||||
beforeId: lastActivityId || undefined,
|
beforeId: lastActivityId || undefined,
|
||||||
}));
|
}));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
yield put(actions.fetchActivities.failure(cardId, error));
|
yield put(actions.fetchActivitiesInBoard.failure(boardId, error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield put(actions.fetchActivities.success(cardId, activities, users));
|
yield put(actions.fetchActivitiesInBoard.success(boardId, activities, users));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* fetchActivitiesInCurrentBoard() {
|
||||||
|
const { boardId } = yield select(selectors.selectPath);
|
||||||
|
|
||||||
|
yield call(fetchActivitiesInBoard, boardId);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* fetchActivitiesInCard(cardId) {
|
||||||
|
const { lastActivityId } = yield select(selectors.selectCardById, cardId);
|
||||||
|
|
||||||
|
yield put(actions.fetchActivitiesInCard(cardId));
|
||||||
|
|
||||||
|
let activities;
|
||||||
|
let users;
|
||||||
|
|
||||||
|
try {
|
||||||
|
({
|
||||||
|
items: activities,
|
||||||
|
included: { users },
|
||||||
|
} = yield call(request, api.getActivitiesInCard, cardId, {
|
||||||
|
beforeId: lastActivityId || undefined,
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
yield put(actions.fetchActivitiesInCard.failure(cardId, error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield put(actions.fetchActivitiesInCard.success(cardId, activities, users));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* fetchActivitiesInCurrentCard() {
|
export function* fetchActivitiesInCurrentCard() {
|
||||||
const { cardId } = yield select(selectors.selectPath);
|
const { cardId } = yield select(selectors.selectPath);
|
||||||
|
|
||||||
yield call(fetchActivities, cardId);
|
yield call(fetchActivitiesInCard, cardId);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* handleActivityCreate(activity) {
|
export function* handleActivityCreate(activity) {
|
||||||
|
@ -44,7 +73,9 @@ export function* handleActivityCreate(activity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
fetchActivities,
|
fetchActivitiesInBoard,
|
||||||
|
fetchActivitiesInCurrentBoard,
|
||||||
|
fetchActivitiesInCard,
|
||||||
fetchActivitiesInCurrentCard,
|
fetchActivitiesInCurrentCard,
|
||||||
handleActivityCreate,
|
handleActivityCreate,
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,6 +10,9 @@ import EntryActionTypes from '../../../constants/EntryActionTypes';
|
||||||
|
|
||||||
export default function* activitiesWatchers() {
|
export default function* activitiesWatchers() {
|
||||||
yield all([
|
yield all([
|
||||||
|
takeEvery(EntryActionTypes.ACTIVITIES_IN_CURRENT_BOARD_FETCH, () =>
|
||||||
|
services.fetchActivitiesInCurrentBoard(),
|
||||||
|
),
|
||||||
takeEvery(EntryActionTypes.ACTIVITIES_IN_CURRENT_CARD_FETCH, () =>
|
takeEvery(EntryActionTypes.ACTIVITIES_IN_CURRENT_CARD_FETCH, () =>
|
||||||
services.fetchActivitiesInCurrentCard(),
|
services.fetchActivitiesInCurrentCard(),
|
||||||
),
|
),
|
||||||
|
|
|
@ -383,6 +383,24 @@ export const selectCustomFieldGroupsForCurrentBoard = createSelector(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const selectActivityIdsForCurrentBoard = createSelector(
|
||||||
|
orm,
|
||||||
|
(state) => selectPath(state).boardId,
|
||||||
|
({ Board }, id) => {
|
||||||
|
if (!id) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const boardModel = Board.withId(id);
|
||||||
|
|
||||||
|
if (!boardModel) {
|
||||||
|
return boardModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return boardModel.getActivitiesModelArray().map((activity) => activity.id);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
export const selectFilterUserIdsForCurrentBoard = createSelector(
|
export const selectFilterUserIdsForCurrentBoard = createSelector(
|
||||||
orm,
|
orm,
|
||||||
(state) => selectPath(state).boardId,
|
(state) => selectPath(state).boardId,
|
||||||
|
@ -447,6 +465,7 @@ export default {
|
||||||
selectFilteredCardIdsForCurrentBoard,
|
selectFilteredCardIdsForCurrentBoard,
|
||||||
selectCustomFieldGroupIdsForCurrentBoard,
|
selectCustomFieldGroupIdsForCurrentBoard,
|
||||||
selectCustomFieldGroupsForCurrentBoard,
|
selectCustomFieldGroupsForCurrentBoard,
|
||||||
|
selectActivityIdsForCurrentBoard,
|
||||||
selectFilterUserIdsForCurrentBoard,
|
selectFilterUserIdsForCurrentBoard,
|
||||||
selectFilterLabelIdsForCurrentBoard,
|
selectFilterLabelIdsForCurrentBoard,
|
||||||
selectIsBoardWithIdExists,
|
selectIsBoardWithIdExists,
|
||||||
|
|
68
server/api/controllers/actions/index-in-board.js
Executable file
68
server/api/controllers/actions/index-in-board.js
Executable file
|
@ -0,0 +1,68 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { idInput } = require('../../../utils/inputs');
|
||||||
|
|
||||||
|
const Errors = {
|
||||||
|
BOARD_NOT_FOUND: {
|
||||||
|
boardNotFound: 'Board not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
inputs: {
|
||||||
|
boardId: {
|
||||||
|
...idInput,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
beforeId: idInput,
|
||||||
|
},
|
||||||
|
|
||||||
|
exits: {
|
||||||
|
boardNotFound: {
|
||||||
|
responseType: 'notFound',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
async fn(inputs) {
|
||||||
|
const { currentUser } = this.req;
|
||||||
|
|
||||||
|
const { board, project } = await sails.helpers.boards
|
||||||
|
.getPathToProjectById(inputs.boardId)
|
||||||
|
.intercept('pathNotFound', () => Errors.BOARD_NOT_FOUND);
|
||||||
|
|
||||||
|
const boardMembership = await BoardMembership.qm.getOneByBoardIdAndUserId(
|
||||||
|
board.id,
|
||||||
|
currentUser.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!boardMembership) {
|
||||||
|
if (currentUser.role !== User.Roles.ADMIN || project.ownerProjectManagerId) {
|
||||||
|
const isProjectManager = await sails.helpers.users.isProjectManager(
|
||||||
|
currentUser.id,
|
||||||
|
project.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isProjectManager) {
|
||||||
|
throw Errors.BOARD_NOT_FOUND; // Forbidden
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const actions = await Action.qm.getByBoardId(board.id, {
|
||||||
|
beforeId: inputs.beforeId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const userIds = sails.helpers.utils.mapRecords(actions, 'userId', true, true);
|
||||||
|
const users = await User.qm.getByIds(userIds);
|
||||||
|
|
||||||
|
return {
|
||||||
|
items: actions,
|
||||||
|
included: {
|
||||||
|
users: sails.helpers.users.presentMany(users, currentUser),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
|
@ -115,6 +115,7 @@ module.exports = {
|
||||||
|
|
||||||
const action = await Action.qm.createOne({
|
const action = await Action.qm.createOne({
|
||||||
...values,
|
...values,
|
||||||
|
boardId: values.card.boardId,
|
||||||
cardId: values.card.id,
|
cardId: values.card.id,
|
||||||
userId: values.user.id,
|
userId: values.user.id,
|
||||||
});
|
});
|
||||||
|
@ -149,10 +150,7 @@ module.exports = {
|
||||||
values: {
|
values: {
|
||||||
action,
|
action,
|
||||||
type: action.type,
|
type: action.type,
|
||||||
data: {
|
data: action.data,
|
||||||
...action.data,
|
|
||||||
card: _.pick(values.card, ['name']),
|
|
||||||
},
|
|
||||||
userId: action.data.user.id,
|
userId: action.data.user.id,
|
||||||
creatorUser: values.user,
|
creatorUser: values.user,
|
||||||
card: values.card,
|
card: values.card,
|
||||||
|
@ -182,10 +180,7 @@ module.exports = {
|
||||||
userId,
|
userId,
|
||||||
action,
|
action,
|
||||||
type: action.type,
|
type: action.type,
|
||||||
data: {
|
data: action.data,
|
||||||
...action.data,
|
|
||||||
card: _.pick(values.card, ['name']),
|
|
||||||
},
|
|
||||||
creatorUser: values.user,
|
creatorUser: values.user,
|
||||||
card: values.card,
|
card: values.card,
|
||||||
},
|
},
|
||||||
|
|
|
@ -35,6 +35,15 @@ module.exports = {
|
||||||
|
|
||||||
await sails.helpers.lists.deleteRelated(lists);
|
await sails.helpers.lists.deleteRelated(lists);
|
||||||
|
|
||||||
|
await Action.qm.update(
|
||||||
|
{
|
||||||
|
boardId: boardIdOrIds,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
boardId: null,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
await NotificationService.qm.delete({
|
await NotificationService.qm.delete({
|
||||||
boardId: boardIdOrIds,
|
boardId: boardIdOrIds,
|
||||||
});
|
});
|
||||||
|
|
|
@ -110,6 +110,7 @@ module.exports = {
|
||||||
type: Action.Types.ADD_MEMBER_TO_CARD,
|
type: Action.Types.ADD_MEMBER_TO_CARD,
|
||||||
data: {
|
data: {
|
||||||
user: _.pick(values.user, ['id', 'name']),
|
user: _.pick(values.user, ['id', 'name']),
|
||||||
|
card: _.pick(values.card, ['name']),
|
||||||
},
|
},
|
||||||
user: inputs.actorUser,
|
user: inputs.actorUser,
|
||||||
card: values.card,
|
card: values.card,
|
||||||
|
|
|
@ -86,6 +86,7 @@ module.exports = {
|
||||||
type: Action.Types.REMOVE_MEMBER_FROM_CARD,
|
type: Action.Types.REMOVE_MEMBER_FROM_CARD,
|
||||||
data: {
|
data: {
|
||||||
user: _.pick(inputs.user, ['id', 'name']),
|
user: _.pick(inputs.user, ['id', 'name']),
|
||||||
|
card: _.pick(inputs.card, ['name']),
|
||||||
},
|
},
|
||||||
user: inputs.actorUser,
|
user: inputs.actorUser,
|
||||||
card: inputs.card,
|
card: inputs.card,
|
||||||
|
|
|
@ -124,6 +124,7 @@ module.exports = {
|
||||||
card,
|
card,
|
||||||
type: Action.Types.CREATE_CARD,
|
type: Action.Types.CREATE_CARD,
|
||||||
data: {
|
data: {
|
||||||
|
card: _.pick(card, ['name']),
|
||||||
list: _.pick(values.list, ['id', 'type', 'name']),
|
list: _.pick(values.list, ['id', 'type', 'name']),
|
||||||
},
|
},
|
||||||
user: values.creatorUser,
|
user: values.creatorUser,
|
||||||
|
|
|
@ -276,6 +276,7 @@ module.exports = {
|
||||||
card,
|
card,
|
||||||
type: Action.Types.CREATE_CARD, // TODO: introduce separate type?
|
type: Action.Types.CREATE_CARD, // TODO: introduce separate type?
|
||||||
data: {
|
data: {
|
||||||
|
card: _.pick(card, ['name']),
|
||||||
list: _.pick(inputs.list, ['id', 'type', 'name']),
|
list: _.pick(inputs.list, ['id', 'type', 'name']),
|
||||||
},
|
},
|
||||||
user: values.creatorUser,
|
user: values.creatorUser,
|
||||||
|
|
|
@ -463,6 +463,7 @@ module.exports = {
|
||||||
card,
|
card,
|
||||||
type: Action.Types.MOVE_CARD,
|
type: Action.Types.MOVE_CARD,
|
||||||
data: {
|
data: {
|
||||||
|
card: _.pick(card, ['name']),
|
||||||
fromList: _.pick(inputs.list, ['id', 'type', 'name']),
|
fromList: _.pick(inputs.list, ['id', 'type', 'name']),
|
||||||
toList: _.pick(values.list, ['id', 'type', 'name']),
|
toList: _.pick(values.list, ['id', 'type', 'name']),
|
||||||
},
|
},
|
||||||
|
|
|
@ -138,6 +138,7 @@ module.exports = {
|
||||||
values: {
|
values: {
|
||||||
type: task.isCompleted ? Action.Types.COMPLETE_TASK : Action.Types.UNCOMPLETE_TASK,
|
type: task.isCompleted ? Action.Types.COMPLETE_TASK : Action.Types.UNCOMPLETE_TASK,
|
||||||
data: {
|
data: {
|
||||||
|
card: _.pick(inputs.card, ['name']),
|
||||||
task: _.pick(task, ['id', 'name']),
|
task: _.pick(task, ['id', 'name']),
|
||||||
},
|
},
|
||||||
user: inputs.actorUser,
|
user: inputs.actorUser,
|
||||||
|
|
|
@ -11,6 +11,20 @@ const create = (arrayOfValues) => Action.createEach(arrayOfValues).fetch();
|
||||||
|
|
||||||
const createOne = (values) => Action.create({ ...values }).fetch();
|
const createOne = (values) => Action.create({ ...values }).fetch();
|
||||||
|
|
||||||
|
const getByBoardId = (boardId, { beforeId } = {}) => {
|
||||||
|
const criteria = {
|
||||||
|
boardId,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (beforeId) {
|
||||||
|
criteria.id = {
|
||||||
|
'<': beforeId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return Action.find(criteria).sort('id DESC').limit(LIMIT);
|
||||||
|
};
|
||||||
|
|
||||||
const getByCardId = (cardId, { beforeId } = {}) => {
|
const getByCardId = (cardId, { beforeId } = {}) => {
|
||||||
const criteria = {
|
const criteria = {
|
||||||
cardId,
|
cardId,
|
||||||
|
@ -33,6 +47,7 @@ const delete_ = (criteria) => Action.destroy(criteria).fetch();
|
||||||
module.exports = {
|
module.exports = {
|
||||||
create,
|
create,
|
||||||
createOne,
|
createOne,
|
||||||
|
getByBoardId,
|
||||||
getByCardId,
|
getByCardId,
|
||||||
update,
|
update,
|
||||||
delete: delete_,
|
delete: delete_,
|
||||||
|
|
|
@ -52,6 +52,10 @@ module.exports = {
|
||||||
// ╠═╣╚═╗╚═╗║ ║║ ║╠═╣ ║ ║║ ║║║║╚═╗
|
// ╠═╣╚═╗╚═╗║ ║║ ║╠═╣ ║ ║║ ║║║║╚═╗
|
||||||
// ╩ ╩╚═╝╚═╝╚═╝╚═╝╩╩ ╩ ╩ ╩╚═╝╝╚╝╚═╝
|
// ╩ ╩╚═╝╚═╝╚═╝╚═╝╩╩ ╩ ╩ ╩╚═╝╝╚╝╚═╝
|
||||||
|
|
||||||
|
boardId: {
|
||||||
|
model: 'Board',
|
||||||
|
columnName: 'board_id',
|
||||||
|
},
|
||||||
cardId: {
|
cardId: {
|
||||||
model: 'Card',
|
model: 'Card',
|
||||||
required: true,
|
required: true,
|
||||||
|
|
|
@ -163,7 +163,8 @@ module.exports.routes = {
|
||||||
'PATCH /api/comments/:id': 'comments/update',
|
'PATCH /api/comments/:id': 'comments/update',
|
||||||
'DELETE /api/comments/:id': 'comments/delete',
|
'DELETE /api/comments/:id': 'comments/delete',
|
||||||
|
|
||||||
'GET /api/cards/:cardId/actions': 'actions/index',
|
'GET /api/boards/:boardId/actions': 'actions/index-in-board',
|
||||||
|
'GET /api/cards/:cardId/actions': 'actions/index-in-card',
|
||||||
|
|
||||||
'GET /api/notifications': 'notifications/index',
|
'GET /api/notifications': 'notifications/index',
|
||||||
'GET /api/notifications/:id': 'notifications/show',
|
'GET /api/notifications/:id': 'notifications/show',
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.up = async (knex) => {
|
||||||
|
await knex.schema.alterTable('action', (table) => {
|
||||||
|
/* Columns */
|
||||||
|
|
||||||
|
table.bigInteger('board_id');
|
||||||
|
|
||||||
|
/* Indexes */
|
||||||
|
|
||||||
|
table.index('board_id');
|
||||||
|
});
|
||||||
|
|
||||||
|
return knex.raw(`
|
||||||
|
UPDATE action
|
||||||
|
SET
|
||||||
|
board_id = card.board_id,
|
||||||
|
data = data || jsonb_build_object('card', jsonb_build_object('name', card.name))
|
||||||
|
FROM card
|
||||||
|
WHERE action.card_id = card.id;
|
||||||
|
`);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (knex) =>
|
||||||
|
knex.schema.table('action', (table) => {
|
||||||
|
table.dropColumn('board_id');
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue