mirror of
https://github.com/plankanban/planka.git
synced 2025-07-18 20:59:44 +02:00
Change id generation algorithm, display notifications total on the main page
This commit is contained in:
parent
9ebc82bf22
commit
3848cc194a
86 changed files with 264 additions and 159 deletions
|
@ -13,7 +13,7 @@ import { ReactComponent as PlusMathIcon } from '../../assets/images/plus-math-ic
|
|||
|
||||
import styles from './Board.module.css';
|
||||
|
||||
const parseDNDId = (dndId) => parseInt(dndId.split(':').pop(), 10);
|
||||
const parseDndId = (dndId) => dndId.split(':')[1];
|
||||
|
||||
const Board = React.memo(
|
||||
({
|
||||
|
@ -51,7 +51,7 @@ const Board = React.memo(
|
|||
return;
|
||||
}
|
||||
|
||||
const id = parseDNDId(draggableId);
|
||||
const id = parseDndId(draggableId);
|
||||
|
||||
switch (type) {
|
||||
case DroppableTypes.LIST:
|
||||
|
@ -59,7 +59,7 @@ const Board = React.memo(
|
|||
|
||||
break;
|
||||
case DroppableTypes.CARD:
|
||||
onCardMove(id, parseDNDId(destination.droppableId), destination.index);
|
||||
onCardMove(id, parseDndId(destination.droppableId), destination.index);
|
||||
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -168,7 +168,7 @@ const Boards = React.memo(
|
|||
|
||||
Boards.propTypes = {
|
||||
items: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||
currentId: PropTypes.number,
|
||||
currentId: PropTypes.string,
|
||||
isEditable: PropTypes.bool.isRequired,
|
||||
onCreate: PropTypes.func.isRequired,
|
||||
onUpdate: PropTypes.func.isRequired,
|
||||
|
|
|
@ -74,7 +74,7 @@ const Card = React.memo(
|
|||
)}
|
||||
<div className={styles.name}>{name}</div>
|
||||
{tasks.length > 0 && <Tasks items={tasks} />}
|
||||
{(dueDate || timer) && (
|
||||
{(dueDate || timer || notificationsTotal > 0) && (
|
||||
<span className={styles.attachments}>
|
||||
{notificationsTotal > 0 && (
|
||||
<span
|
||||
|
@ -168,7 +168,7 @@ const Card = React.memo(
|
|||
);
|
||||
|
||||
Card.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
id: PropTypes.string.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
dueDate: PropTypes.instanceOf(Date),
|
||||
|
|
|
@ -110,7 +110,7 @@ const List = React.memo(
|
|||
);
|
||||
|
||||
List.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
id: PropTypes.string.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
isPersisted: PropTypes.bool.isRequired,
|
||||
|
|
|
@ -31,6 +31,9 @@ const Projects = React.memo(({
|
|||
}
|
||||
>
|
||||
<div className={classNames(styles.card, styles.open)}>
|
||||
{item.notificationsTotal > 0 && (
|
||||
<span className={styles.notification}>{item.notificationsTotal}</span>
|
||||
)}
|
||||
<div className={styles.cardOverlay} />
|
||||
<div className={styles.openTitle}>{item.name}</div>
|
||||
</div>
|
||||
|
@ -69,7 +72,7 @@ const Projects = React.memo(({
|
|||
|
||||
Projects.propTypes = {
|
||||
items: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||
currentId: PropTypes.number,
|
||||
currentId: PropTypes.string,
|
||||
isEditable: PropTypes.bool.isRequired,
|
||||
onAdd: PropTypes.func.isRequired,
|
||||
};
|
||||
|
|
|
@ -59,6 +59,20 @@
|
|||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.notification {
|
||||
background: #eb5a46;
|
||||
color: #fff;
|
||||
float: right;
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
padding: 0px 6px;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
outline: none;
|
||||
text-align: left;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
.open {
|
||||
background: #555;
|
||||
background-size: cover;
|
||||
|
|
|
@ -2,15 +2,9 @@ import { call, put, select } from 'redux-saga/effects';
|
|||
|
||||
import { goToBoardService, goToProjectService } from './router';
|
||||
import { createBoardRequest, deleteBoardRequest, updateBoardRequest } from '../requests';
|
||||
import {
|
||||
boardByIdSelector,
|
||||
maxIdSelector,
|
||||
nextBoardPositionSelector,
|
||||
pathSelector,
|
||||
} from '../../../selectors';
|
||||
import { boardByIdSelector, nextBoardPositionSelector, pathSelector } from '../../../selectors';
|
||||
import { createBoard, deleteBoard, updateBoard } from '../../../actions';
|
||||
import { nextLocalId } from '../../../utils/local-id';
|
||||
import { Board } from '../../../models';
|
||||
import { createLocalId } from '../../../utils/local-id';
|
||||
|
||||
export function* createBoardService(projectId, data) {
|
||||
const nextData = {
|
||||
|
@ -18,7 +12,7 @@ export function* createBoardService(projectId, data) {
|
|||
position: yield select(nextBoardPositionSelector, projectId),
|
||||
};
|
||||
|
||||
const localId = nextLocalId(yield select(maxIdSelector, Board.modelName));
|
||||
const localId = yield call(createLocalId);
|
||||
|
||||
yield put(
|
||||
createBoard({
|
||||
|
|
|
@ -2,10 +2,9 @@ import { call, put, select } from 'redux-saga/effects';
|
|||
|
||||
import { goToBoardService } from './router';
|
||||
import { createCardRequest, deleteCardRequest, updateCardRequest } from '../requests';
|
||||
import { maxIdSelector, nextCardPositionSelector, pathSelector } from '../../../selectors';
|
||||
import { nextCardPositionSelector, pathSelector } from '../../../selectors';
|
||||
import { createCard, deleteCard, updateCard } from '../../../actions';
|
||||
import { nextLocalId } from '../../../utils/local-id';
|
||||
import { Card } from '../../../models';
|
||||
import { createLocalId } from '../../../utils/local-id';
|
||||
|
||||
export function* createCardService(listId, data) {
|
||||
const nextData = {
|
||||
|
@ -13,7 +12,7 @@ export function* createCardService(listId, data) {
|
|||
position: yield select(nextCardPositionSelector, listId),
|
||||
};
|
||||
|
||||
const localId = nextLocalId(yield select(maxIdSelector, Card.modelName));
|
||||
const localId = yield call(createLocalId);
|
||||
|
||||
yield put(
|
||||
createCard({
|
||||
|
|
|
@ -5,14 +5,13 @@ import {
|
|||
deleteCommentActionRequest,
|
||||
updateCommentActionRequest,
|
||||
} from '../requests';
|
||||
import { currentUserIdSelector, maxIdSelector, pathSelector } from '../../../selectors';
|
||||
import { currentUserIdSelector, pathSelector } from '../../../selectors';
|
||||
import { createCommentAction, deleteCommentAction, updateCommentAction } from '../../../actions';
|
||||
import { nextLocalId } from '../../../utils/local-id';
|
||||
import { Action } from '../../../models';
|
||||
import { createLocalId } from '../../../utils/local-id';
|
||||
import { ActionTypes } from '../../../constants/Enums';
|
||||
|
||||
export function* createCommentActionService(cardId, data) {
|
||||
const localId = nextLocalId(yield select(maxIdSelector, Action.modelName));
|
||||
const localId = yield call(createLocalId);
|
||||
const userId = yield select(currentUserIdSelector);
|
||||
|
||||
yield put(
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
deleteLabelRequest,
|
||||
updateLabelRequest,
|
||||
} from '../requests';
|
||||
import { maxIdSelector, pathSelector } from '../../../selectors';
|
||||
import { pathSelector } from '../../../selectors';
|
||||
import {
|
||||
addLabelToBoardFilter,
|
||||
addLabelToCard,
|
||||
|
@ -17,11 +17,10 @@ import {
|
|||
removeLabelFromCard,
|
||||
updateLabel,
|
||||
} from '../../../actions';
|
||||
import { nextLocalId } from '../../../utils/local-id';
|
||||
import { Label } from '../../../models';
|
||||
import { createLocalId } from '../../../utils/local-id';
|
||||
|
||||
export function* createLabelService(boardId, data) {
|
||||
const localId = nextLocalId(yield select(maxIdSelector, Label.modelName));
|
||||
const localId = yield call(createLocalId);
|
||||
|
||||
yield put(
|
||||
createLabel({
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
import { call, put, select } from 'redux-saga/effects';
|
||||
|
||||
import { createListRequest, deleteListRequest, updateListRequest } from '../requests';
|
||||
import {
|
||||
listByIdSelector,
|
||||
maxIdSelector,
|
||||
nextListPositionSelector,
|
||||
pathSelector,
|
||||
} from '../../../selectors';
|
||||
import { listByIdSelector, nextListPositionSelector, pathSelector } from '../../../selectors';
|
||||
import { createList, deleteList, updateList } from '../../../actions';
|
||||
import { nextLocalId } from '../../../utils/local-id';
|
||||
import { List } from '../../../models';
|
||||
import { createLocalId } from '../../../utils/local-id';
|
||||
|
||||
export function* createListService(boardId, data) {
|
||||
const nextData = {
|
||||
|
@ -17,7 +11,7 @@ export function* createListService(boardId, data) {
|
|||
position: yield select(nextListPositionSelector, boardId),
|
||||
};
|
||||
|
||||
const localId = nextLocalId(yield select(maxIdSelector, List.modelName));
|
||||
const localId = yield call(createLocalId);
|
||||
|
||||
yield put(
|
||||
createList({
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import { call, put, select } from 'redux-saga/effects';
|
||||
|
||||
import { createProjectMembershipRequest, deleteProjectMembershipRequest } from '../requests';
|
||||
import { maxIdSelector, pathSelector } from '../../../selectors';
|
||||
import { pathSelector } from '../../../selectors';
|
||||
import { createProjectMembership, deleteProjectMembership } from '../../../actions';
|
||||
import { nextLocalId } from '../../../utils/local-id';
|
||||
import { ProjectMembership } from '../../../models';
|
||||
import { createLocalId } from '../../../utils/local-id';
|
||||
|
||||
export function* createProjectMembershipService(projectId, data) {
|
||||
const localId = nextLocalId(yield select(maxIdSelector, ProjectMembership.modelName));
|
||||
const localId = yield call(createLocalId);
|
||||
|
||||
yield put(
|
||||
createProjectMembership({
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import { call, put, select } from 'redux-saga/effects';
|
||||
|
||||
import { createTaskRequest, deleteTaskRequest, updateTaskRequest } from '../requests';
|
||||
import { maxIdSelector, pathSelector } from '../../../selectors';
|
||||
import { pathSelector } from '../../../selectors';
|
||||
import { createTask, deleteTask, updateTask } from '../../../actions';
|
||||
import { nextLocalId } from '../../../utils/local-id';
|
||||
import { Task } from '../../../models';
|
||||
import { createLocalId } from '../../../utils/local-id';
|
||||
|
||||
export function* createTaskService(cardId, data) {
|
||||
const localId = nextLocalId(yield select(maxIdSelector, Task.modelName));
|
||||
const localId = yield call(createLocalId);
|
||||
|
||||
yield put(
|
||||
createTask({
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
export const maxIdSelector = ({ db }, modelName) => db[modelName].meta.maxId;
|
||||
|
||||
export const accessTokenSelector = ({ auth: { accessToken } }) => accessToken;
|
||||
|
||||
export const isAppInitializingSelector = ({ app: { isInitializing } }) => isInitializing;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export const nextLocalId = (maxId = 0) => maxId + Date.now() / 10000000000000;
|
||||
export const createLocalId = () => `local:${Date.now()}`;
|
||||
|
||||
export const isLocalId = (id) => id % 1 !== 0;
|
||||
export const isLocalId = (id) => id.startsWith('local:');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue