mirror of
https://github.com/plankanban/planka.git
synced 2025-07-18 20:59:44 +02:00
Project managers, board members, auto-update after reconnection, refactoring
This commit is contained in:
parent
7956503a46
commit
fe91b5241e
478 changed files with 21226 additions and 19495 deletions
14245
client/package-lock.json
generated
14245
client/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -32,8 +32,7 @@
|
||||||
"extends": [
|
"extends": [
|
||||||
"airbnb",
|
"airbnb",
|
||||||
"airbnb/hooks",
|
"airbnb/hooks",
|
||||||
"plugin:prettier/recommended",
|
"plugin:prettier/recommended"
|
||||||
"prettier/react"
|
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"import/no-extraneous-dependencies": [
|
"import/no-extraneous-dependencies": [
|
||||||
|
@ -58,28 +57,28 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"connected-react-router": "^6.8.0",
|
"connected-react-router": "^6.8.0",
|
||||||
"date-fns": "^2.17.0",
|
"date-fns": "^2.22.1",
|
||||||
"dequal": "^2.0.2",
|
"dequal": "^2.0.2",
|
||||||
"history": "^4.10.1",
|
"history": "^4.10.1",
|
||||||
"i18next": "^19.8.7",
|
"i18next": "^20.3.2",
|
||||||
"i18next-browser-languagedetector": "^6.0.1",
|
"i18next-browser-languagedetector": "^6.1.2",
|
||||||
"initials": "^3.1.1",
|
"initials": "^3.1.1",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.20",
|
||||||
"node-sass": "^4.14.1",
|
"node-sass": "^6.0.0",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-beautiful-dnd": "^13.0.0",
|
"react-beautiful-dnd": "^13.0.0",
|
||||||
"react-datepicker": "^3.4.1",
|
"react-datepicker": "^4.1.1",
|
||||||
"react-dom": "^17.0.1",
|
"react-dom": "^17.0.1",
|
||||||
"react-dropzone": "^11.3.1",
|
"react-dropzone": "^11.3.1",
|
||||||
"react-i18next": "^11.8.6",
|
"react-i18next": "^11.11.0",
|
||||||
"react-input-mask": "^2.0.4",
|
"react-input-mask": "^2.0.4",
|
||||||
"react-markdown": "^5.0.3",
|
"react-markdown": "^6.0.2",
|
||||||
"react-redux": "^7.2.2",
|
"react-redux": "^7.2.4",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "4.0.2",
|
"react-scripts": "4.0.3",
|
||||||
"react-textarea-autosize": "^8.3.1",
|
"react-textarea-autosize": "^8.3.3",
|
||||||
"redux": "^4.0.5",
|
"redux": "^4.1.0",
|
||||||
"redux-logger": "^3.0.6",
|
"redux-logger": "^3.0.6",
|
||||||
"redux-orm": "^0.16.2",
|
"redux-orm": "^0.16.2",
|
||||||
"redux-saga": "^1.1.3",
|
"redux-saga": "^1.1.3",
|
||||||
|
@ -88,23 +87,23 @@
|
||||||
"sails.io.js": "^1.2.1",
|
"sails.io.js": "^1.2.1",
|
||||||
"semantic-ui-react": "^2.0.3",
|
"semantic-ui-react": "^2.0.3",
|
||||||
"socket.io-client": "^2.3.1",
|
"socket.io-client": "^2.3.1",
|
||||||
"validator": "^13.5.2",
|
"validator": "^13.6.0",
|
||||||
"whatwg-fetch": "^3.5.0"
|
"whatwg-fetch": "^3.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.2",
|
||||||
"chai": "^4.3.0",
|
"chai": "^4.3.0",
|
||||||
"enzyme": "^3.11.0",
|
"enzyme": "^3.11.0",
|
||||||
"enzyme-adapter-react-16": "^1.15.6",
|
"eslint": "^7.29.0",
|
||||||
"eslint": "^7.19.0",
|
|
||||||
"eslint-config-airbnb": "^18.2.1",
|
"eslint-config-airbnb": "^18.2.1",
|
||||||
"eslint-config-prettier": "^7.2.0",
|
"eslint-config-prettier": "^8.3.0",
|
||||||
"eslint-plugin-import": "^2.22.1",
|
"eslint-plugin-import": "^2.23.4",
|
||||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||||
"eslint-plugin-prettier": "^3.3.1",
|
"eslint-plugin-prettier": "^3.4.0",
|
||||||
"eslint-plugin-react": "^7.22.0",
|
"eslint-plugin-react": "^7.24.0",
|
||||||
"eslint-plugin-react-hooks": "^4.2.0",
|
"eslint-plugin-react-hooks": "^4.2.0",
|
||||||
"jest-enzyme": "^7.1.2",
|
"jest-enzyme": "^7.1.2",
|
||||||
"prettier": "2.2.1",
|
"prettier": "2.3.1",
|
||||||
"react-test-renderer": "^17.0.1"
|
"react-test-renderer": "^17.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,21 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Events */
|
export const handleActionCreate = (action) => ({
|
||||||
|
type: ActionTypes.ACTION_CREATE_HANDLE,
|
||||||
export const createActionReceived = (action) => ({
|
|
||||||
type: ActionTypes.ACTION_CREATE_RECEIVED,
|
|
||||||
payload: {
|
payload: {
|
||||||
action,
|
action,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateActionReceived = (action) => ({
|
export const handleActionUpdate = (action) => ({
|
||||||
type: ActionTypes.ACTION_UPDATE_RECEIVED,
|
type: ActionTypes.ACTION_UPDATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
action,
|
action,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteActionReceived = (action) => ({
|
export const handleActionDelete = (action) => ({
|
||||||
type: ActionTypes.ACTION_DELETE_RECEIVED,
|
type: ActionTypes.ACTION_DELETE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
action,
|
action,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Events */
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
|
export const fetchActions = (cardId) => ({
|
||||||
export const fetchActionsRequested = (cardId) => ({
|
type: ActionTypes.ACTIONS_FETCH,
|
||||||
type: ActionTypes.ACTIONS_FETCH_REQUESTED,
|
|
||||||
payload: {
|
payload: {
|
||||||
cardId,
|
cardId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const fetchActionsSucceeded = (cardId, actions, users) => ({
|
fetchActions.success = (cardId, actions, users) => ({
|
||||||
type: ActionTypes.ACTIONS_FETCH_SUCCEEDED,
|
type: ActionTypes.ACTIONS_FETCH__SUCCESS,
|
||||||
payload: {
|
payload: {
|
||||||
cardId,
|
cardId,
|
||||||
actions,
|
actions,
|
||||||
|
@ -18,8 +17,8 @@ export const fetchActionsSucceeded = (cardId, actions, users) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const fetchActionsFailed = (cardId, error) => ({
|
fetchActions.failure = (cardId, error) => ({
|
||||||
type: ActionTypes.ACTIONS_FETCH_FAILED,
|
type: ActionTypes.ACTIONS_FETCH__FAILURE,
|
||||||
payload: {
|
payload: {
|
||||||
cardId,
|
cardId,
|
||||||
error,
|
error,
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
export const createAttachment = (attachment) => ({
|
export const createAttachment = (attachment) => ({
|
||||||
type: ActionTypes.ATTACHMENT_CREATE,
|
type: ActionTypes.ATTACHMENT_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -9,6 +7,29 @@ export const createAttachment = (attachment) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
createAttachment.success = (localId, attachment) => ({
|
||||||
|
type: ActionTypes.ATTACHMENT_CREATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
attachment,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createAttachment.failure = (localId, error) => ({
|
||||||
|
type: ActionTypes.ATTACHMENT_CREATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleAttachmentCreate = (attachment) => ({
|
||||||
|
type: ActionTypes.ATTACHMENT_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
attachment,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateAttachment = (id, data) => ({
|
export const updateAttachment = (id, data) => ({
|
||||||
type: ActionTypes.ATTACHMENT_UPDATE,
|
type: ActionTypes.ATTACHMENT_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -17,6 +38,28 @@ export const updateAttachment = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateAttachment.success = (attachment) => ({
|
||||||
|
type: ActionTypes.ATTACHMENT_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
attachment,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateAttachment.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.ATTACHMENT_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleAttachmentUpdate = (attachment) => ({
|
||||||
|
type: ActionTypes.ATTACHMENT_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
attachment,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const deleteAttachment = (id) => ({
|
export const deleteAttachment = (id) => ({
|
||||||
type: ActionTypes.ATTACHMENT_DELETE,
|
type: ActionTypes.ATTACHMENT_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -24,93 +67,23 @@ export const deleteAttachment = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Events */
|
deleteAttachment.success = (attachment) => ({
|
||||||
|
type: ActionTypes.ATTACHMENT_DELETE__SUCCESS,
|
||||||
export const createAttachmentRequested = (localId, data) => ({
|
|
||||||
type: ActionTypes.ATTACHMENT_CREATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createAttachmentSucceeded = (localId, attachment) => ({
|
|
||||||
type: ActionTypes.ATTACHMENT_CREATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
attachment,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createAttachmentFailed = (localId, error) => ({
|
|
||||||
type: ActionTypes.ATTACHMENT_CREATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createAttachmentReceived = (attachment) => ({
|
|
||||||
type: ActionTypes.ATTACHMENT_CREATE_RECEIVED,
|
|
||||||
payload: {
|
payload: {
|
||||||
attachment,
|
attachment,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateAttachmentRequested = (id, data) => ({
|
deleteAttachment.failure = (id, error) => ({
|
||||||
type: ActionTypes.ATTACHMENT_UPDATE_REQUESTED,
|
type: ActionTypes.ATTACHMENT_DELETE__FAILURE,
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateAttachmentSucceeded = (attachment) => ({
|
|
||||||
type: ActionTypes.ATTACHMENT_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
attachment,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateAttachmentFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.ATTACHMENT_UPDATE_FAILED,
|
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
error,
|
error,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateAttachmentReceived = (attachment) => ({
|
export const handleAttachmentDelete = (attachment) => ({
|
||||||
type: ActionTypes.ATTACHMENT_UPDATE_RECEIVED,
|
type: ActionTypes.ATTACHMENT_DELETE_HANDLE,
|
||||||
payload: {
|
|
||||||
attachment,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteAttachmentRequested = (id) => ({
|
|
||||||
type: ActionTypes.ATTACHMENT_DELETE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteAttachmentSucceeded = (attachment) => ({
|
|
||||||
type: ActionTypes.ATTACHMENT_DELETE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
attachment,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteAttachmentFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.ATTACHMENT_DELETE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteAttachmentReceived = (attachment) => ({
|
|
||||||
type: ActionTypes.ATTACHMENT_DELETE_RECEIVED,
|
|
||||||
payload: {
|
payload: {
|
||||||
attachment,
|
attachment,
|
||||||
},
|
},
|
||||||
|
|
97
client/src/actions/board-membership.js
Normal file
97
client/src/actions/board-membership.js
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
|
export const createBoardMembership = (boardMembership) => ({
|
||||||
|
type: ActionTypes.BOARD_MEMBERSHIP_CREATE,
|
||||||
|
payload: {
|
||||||
|
boardMembership,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createBoardMembership.success = (localId, boardMembership) => ({
|
||||||
|
type: ActionTypes.BOARD_MEMBERSHIP_CREATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
boardMembership,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createBoardMembership.failure = (localId, error) => ({
|
||||||
|
type: ActionTypes.BOARD_MEMBERSHIP_CREATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleBoardMembershipCreate = (
|
||||||
|
boardMembership,
|
||||||
|
project,
|
||||||
|
board,
|
||||||
|
users,
|
||||||
|
projectManagers,
|
||||||
|
boards,
|
||||||
|
boardMemberships,
|
||||||
|
labels,
|
||||||
|
lists,
|
||||||
|
cards,
|
||||||
|
cardMemberships,
|
||||||
|
cardLabels,
|
||||||
|
tasks,
|
||||||
|
attachments,
|
||||||
|
) => ({
|
||||||
|
type: ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
boardMembership,
|
||||||
|
project,
|
||||||
|
board,
|
||||||
|
users,
|
||||||
|
projectManagers,
|
||||||
|
boards,
|
||||||
|
boardMemberships,
|
||||||
|
labels,
|
||||||
|
lists,
|
||||||
|
cards,
|
||||||
|
cardMemberships,
|
||||||
|
cardLabels,
|
||||||
|
tasks,
|
||||||
|
attachments,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
handleBoardMembershipCreate.fetchProject = (id, currentUserId, currentBoardId) => ({
|
||||||
|
type: ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE__PROJECT_FETCH,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
currentUserId,
|
||||||
|
currentBoardId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const deleteBoardMembership = (id) => ({
|
||||||
|
type: ActionTypes.BOARD_MEMBERSHIP_DELETE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteBoardMembership.success = (boardMembership) => ({
|
||||||
|
type: ActionTypes.BOARD_MEMBERSHIP_DELETE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
boardMembership,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteBoardMembership.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.BOARD_MEMBERSHIP_DELETE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleBoardMembershipDelete = (boardMembership) => ({
|
||||||
|
type: ActionTypes.BOARD_MEMBERSHIP_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
boardMembership,
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,7 +1,5 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
export const createBoard = (board) => ({
|
export const createBoard = (board) => ({
|
||||||
type: ActionTypes.BOARD_CREATE,
|
type: ActionTypes.BOARD_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -9,6 +7,74 @@ export const createBoard = (board) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
createBoard.success = (localId, board, boardMemberships) => ({
|
||||||
|
type: ActionTypes.BOARD_CREATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
board,
|
||||||
|
boardMemberships,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createBoard.failure = (localId, error) => ({
|
||||||
|
type: ActionTypes.BOARD_CREATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleBoardCreate = (board) => ({
|
||||||
|
type: ActionTypes.BOARD_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
board,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const fetchBoard = (id) => ({
|
||||||
|
type: ActionTypes.BOARD_FETCH,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
fetchBoard.success = (
|
||||||
|
board,
|
||||||
|
users,
|
||||||
|
projects,
|
||||||
|
boardMemberships,
|
||||||
|
labels,
|
||||||
|
lists,
|
||||||
|
cards,
|
||||||
|
cardMemberships,
|
||||||
|
cardLabels,
|
||||||
|
tasks,
|
||||||
|
attachments,
|
||||||
|
) => ({
|
||||||
|
type: ActionTypes.BOARD_FETCH__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
board,
|
||||||
|
users,
|
||||||
|
projects,
|
||||||
|
boardMemberships,
|
||||||
|
labels,
|
||||||
|
lists,
|
||||||
|
cards,
|
||||||
|
cardMemberships,
|
||||||
|
cardLabels,
|
||||||
|
tasks,
|
||||||
|
attachments,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
fetchBoard.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.BOARD_FETCH__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateBoard = (id, data) => ({
|
export const updateBoard = (id, data) => ({
|
||||||
type: ActionTypes.BOARD_UPDATE,
|
type: ActionTypes.BOARD_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -17,6 +83,28 @@ export const updateBoard = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateBoard.success = (board) => ({
|
||||||
|
type: ActionTypes.BOARD_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
board,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateBoard.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.BOARD_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleBoardUpdate = (board) => ({
|
||||||
|
type: ActionTypes.BOARD_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
board,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const deleteBoard = (id) => ({
|
export const deleteBoard = (id) => ({
|
||||||
type: ActionTypes.BOARD_DELETE,
|
type: ActionTypes.BOARD_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -24,135 +112,23 @@ export const deleteBoard = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Events */
|
deleteBoard.success = (board) => ({
|
||||||
|
type: ActionTypes.BOARD_DELETE__SUCCESS,
|
||||||
export const createBoardRequested = (localId, data) => ({
|
|
||||||
type: ActionTypes.BOARD_CREATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createBoardSucceeded = (localId, board, lists, labels) => ({
|
|
||||||
type: ActionTypes.BOARD_CREATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
board,
|
|
||||||
lists,
|
|
||||||
labels,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createBoardFailed = (localId, error) => ({
|
|
||||||
type: ActionTypes.BOARD_CREATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createBoardReceived = (board, lists, labels) => ({
|
|
||||||
type: ActionTypes.BOARD_CREATE_RECEIVED,
|
|
||||||
payload: {
|
payload: {
|
||||||
board,
|
board,
|
||||||
lists,
|
|
||||||
labels,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const fetchBoardRequested = (id) => ({
|
deleteBoard.failure = (id, error) => ({
|
||||||
type: ActionTypes.BOARD_FETCH_REQUESTED,
|
type: ActionTypes.BOARD_DELETE__FAILURE,
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchBoardSucceeded = (
|
|
||||||
board,
|
|
||||||
labels,
|
|
||||||
lists,
|
|
||||||
cards,
|
|
||||||
cardMemberships,
|
|
||||||
cardLabels,
|
|
||||||
tasks,
|
|
||||||
attachments,
|
|
||||||
) => ({
|
|
||||||
type: ActionTypes.BOARD_FETCH_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
board,
|
|
||||||
labels,
|
|
||||||
lists,
|
|
||||||
cards,
|
|
||||||
cardMemberships,
|
|
||||||
cardLabels,
|
|
||||||
tasks,
|
|
||||||
attachments,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchBoardFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.BOARD_FETCH_FAILED,
|
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
error,
|
error,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateBoardRequested = (id, data) => ({
|
export const handleBoardDelete = (board) => ({
|
||||||
type: ActionTypes.BOARD_UPDATE_REQUESTED,
|
type: ActionTypes.BOARD_DELETE_HANDLE,
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateBoardSucceeded = (board) => ({
|
|
||||||
type: ActionTypes.BOARD_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
board,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateBoardFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.BOARD_UPDATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateBoardReceived = (board) => ({
|
|
||||||
type: ActionTypes.BOARD_UPDATE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
board,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteBoardRequested = (id) => ({
|
|
||||||
type: ActionTypes.BOARD_DELETE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteBoardSucceeded = (board) => ({
|
|
||||||
type: ActionTypes.BOARD_DELETE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
board,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteBoardFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.BOARD_DELETE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteBoardReceived = (board) => ({
|
|
||||||
type: ActionTypes.BOARD_DELETE_RECEIVED,
|
|
||||||
payload: {
|
payload: {
|
||||||
board,
|
board,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
|
||||||
|
|
||||||
/* Events */
|
|
||||||
|
|
||||||
export const createCardLabelRequested = (data) => ({
|
|
||||||
type: ActionTypes.CARD_LABEL_CREATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createCardLabelSucceeded = (cardLabel) => ({
|
|
||||||
type: ActionTypes.CARD_LABEL_CREATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
cardLabel,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createCardLabelFailed = (error) => ({
|
|
||||||
type: ActionTypes.CARD_LABEL_CREATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createCardLabelReceived = (cardLabel) => ({
|
|
||||||
type: ActionTypes.CARD_LABEL_CREATE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
cardLabel,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCardLabelRequested = (cardId, labelId) => ({
|
|
||||||
type: ActionTypes.CARD_LABEL_DELETE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
cardId,
|
|
||||||
labelId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCardLabelSucceeded = (cardLabel) => ({
|
|
||||||
type: ActionTypes.CARD_LABEL_DELETE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
cardLabel,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCardLabelFailed = (cardId, labelId, error) => ({
|
|
||||||
type: ActionTypes.CARD_LABEL_DELETE_FAILED,
|
|
||||||
payload: {
|
|
||||||
cardId,
|
|
||||||
labelId,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCardLabelReceived = (cardLabel) => ({
|
|
||||||
type: ActionTypes.CARD_LABEL_DELETE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
cardLabel,
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,62 +0,0 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
|
||||||
|
|
||||||
/* Events */
|
|
||||||
|
|
||||||
export const createCardMembershipRequested = (data) => ({
|
|
||||||
type: ActionTypes.CARD_MEMBERSHIP_CREATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createCardMembershipSucceeded = (cardMembership) => ({
|
|
||||||
type: ActionTypes.CARD_MEMBERSHIP_CREATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
cardMembership,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createCardMembershipFailed = (error) => ({
|
|
||||||
type: ActionTypes.CARD_MEMBERSHIP_CREATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createCardMembershipReceived = (cardMembership) => ({
|
|
||||||
type: ActionTypes.CARD_MEMBERSHIP_CREATE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
cardMembership,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCardMembershipRequested = (cardId, userId) => ({
|
|
||||||
type: ActionTypes.CARD_MEMBERSHIP_DELETE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
cardId,
|
|
||||||
userId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCardMembershipSucceeded = (cardMembership) => ({
|
|
||||||
type: ActionTypes.CARD_MEMBERSHIP_DELETE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
cardMembership,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCardMembershipFailed = (cardId, userId, error) => ({
|
|
||||||
type: ActionTypes.CARD_MEMBERSHIP_DELETE_FAILED,
|
|
||||||
payload: {
|
|
||||||
cardId,
|
|
||||||
userId,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCardMembershipReceived = (cardMembership) => ({
|
|
||||||
type: ActionTypes.CARD_MEMBERSHIP_DELETE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
cardMembership,
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,7 +1,5 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
export const createCard = (card) => ({
|
export const createCard = (card) => ({
|
||||||
type: ActionTypes.CARD_CREATE,
|
type: ActionTypes.CARD_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -9,6 +7,29 @@ export const createCard = (card) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
createCard.success = (localId, card) => ({
|
||||||
|
type: ActionTypes.CARD_CREATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
card,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createCard.failure = (localId, error) => ({
|
||||||
|
type: ActionTypes.CARD_CREATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleCardCreate = (card) => ({
|
||||||
|
type: ActionTypes.CARD_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
card,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateCard = (id, data) => ({
|
export const updateCard = (id, data) => ({
|
||||||
type: ActionTypes.CARD_UPDATE,
|
type: ActionTypes.CARD_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -17,6 +38,28 @@ export const updateCard = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateCard.success = (card) => ({
|
||||||
|
type: ActionTypes.CARD_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
card,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateCard.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.CARD_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleCardUpdate = (card) => ({
|
||||||
|
type: ActionTypes.CARD_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
card,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const deleteCard = (id) => ({
|
export const deleteCard = (id) => ({
|
||||||
type: ActionTypes.CARD_DELETE,
|
type: ActionTypes.CARD_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -24,130 +67,23 @@ export const deleteCard = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Events */
|
deleteCard.success = (card) => ({
|
||||||
|
type: ActionTypes.CARD_DELETE__SUCCESS,
|
||||||
export const createCardRequested = (localId, data) => ({
|
|
||||||
type: ActionTypes.CARD_CREATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createCardSucceeded = (
|
|
||||||
localId,
|
|
||||||
card,
|
|
||||||
cardMemberships,
|
|
||||||
cardLabels,
|
|
||||||
tasks,
|
|
||||||
attachments,
|
|
||||||
) => ({
|
|
||||||
type: ActionTypes.CARD_CREATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
card,
|
|
||||||
cardMemberships,
|
|
||||||
cardLabels,
|
|
||||||
tasks,
|
|
||||||
attachments,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createCardFailed = (localId, error) => ({
|
|
||||||
type: ActionTypes.CARD_CREATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createCardReceived = (card, cardMemberships, cardLabels, tasks, attachments) => ({
|
|
||||||
type: ActionTypes.CARD_CREATE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
card,
|
|
||||||
cardMemberships,
|
|
||||||
cardLabels,
|
|
||||||
tasks,
|
|
||||||
attachments,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchCardRequested = (id) => ({
|
|
||||||
type: ActionTypes.CARD_FETCH_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchCardSucceeded = (card) => ({
|
|
||||||
type: ActionTypes.CARD_FETCH_SUCCEEDED,
|
|
||||||
payload: {
|
payload: {
|
||||||
card,
|
card,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const fetchCardFailed = (id, error) => ({
|
deleteCard.failure = (id, error) => ({
|
||||||
type: ActionTypes.CARD_FETCH_FAILED,
|
type: ActionTypes.CARD_DELETE__FAILURE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
error,
|
error,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateCardRequested = (id, data) => ({
|
export const handleCardDelete = (card) => ({
|
||||||
type: ActionTypes.CARD_UPDATE_REQUESTED,
|
type: ActionTypes.CARD_DELETE_HANDLE,
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateCardSucceeded = (card) => ({
|
|
||||||
type: ActionTypes.CARD_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
card,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateCardFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.CARD_UPDATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateCardReceived = (card) => ({
|
|
||||||
type: ActionTypes.CARD_UPDATE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
card,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCardRequested = (id) => ({
|
|
||||||
type: ActionTypes.CARD_DELETE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCardSucceeded = (card) => ({
|
|
||||||
type: ActionTypes.CARD_DELETE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
card,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCardFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.CARD_DELETE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCardReceived = (card) => ({
|
|
||||||
type: ActionTypes.CARD_DELETE_RECEIVED,
|
|
||||||
payload: {
|
payload: {
|
||||||
card,
|
card,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
export const createCommentAction = (action) => ({
|
export const createCommentAction = (action) => ({
|
||||||
type: ActionTypes.COMMENT_ACTION_CREATE,
|
type: ActionTypes.COMMENT_ACTION_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -9,6 +7,22 @@ export const createCommentAction = (action) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
createCommentAction.success = (localId, action) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTION_CREATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
action,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createCommentAction.failure = (localId, error) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTION_CREATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateCommentAction = (id, data) => ({
|
export const updateCommentAction = (id, data) => ({
|
||||||
type: ActionTypes.COMMENT_ACTION_UPDATE,
|
type: ActionTypes.COMMENT_ACTION_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -17,6 +31,21 @@ export const updateCommentAction = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateCommentAction.success = (action) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTION_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
action,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateCommentAction.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTION_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const deleteCommentAction = (id) => ({
|
export const deleteCommentAction = (id) => ({
|
||||||
type: ActionTypes.COMMENT_ACTION_DELETE,
|
type: ActionTypes.COMMENT_ACTION_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -24,71 +53,15 @@ export const deleteCommentAction = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Events */
|
deleteCommentAction.success = (action) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTION_DELETE__SUCCESS,
|
||||||
export const createCommentActionRequested = (localId, data) => ({
|
|
||||||
type: ActionTypes.COMMENT_ACTION_CREATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createCommentActionSucceeded = (localId, action) => ({
|
|
||||||
type: ActionTypes.COMMENT_ACTION_CREATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
action,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createCommentActionFailed = (localId, error) => ({
|
|
||||||
type: ActionTypes.COMMENT_ACTION_CREATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateCommentActionRequested = (id, data) => ({
|
|
||||||
type: ActionTypes.COMMENT_ACTION_UPDATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateCommentActionSucceeded = (action) => ({
|
|
||||||
type: ActionTypes.COMMENT_ACTION_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
payload: {
|
||||||
action,
|
action,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateCommentActionFailed = (id, error) => ({
|
deleteCommentAction.failure = (id, error) => ({
|
||||||
type: ActionTypes.COMMENT_ACTION_UPDATE_FAILED,
|
type: ActionTypes.COMMENT_ACTION_DELETE__FAILURE,
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCommentActionRequested = (id) => ({
|
|
||||||
type: ActionTypes.COMMENT_ACTION_DELETE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCommentActionSucceeded = (action) => ({
|
|
||||||
type: ActionTypes.COMMENT_ACTION_DELETE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
action,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCommentActionFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.COMMENT_ACTION_DELETE_FAILED,
|
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
error,
|
error,
|
||||||
|
|
|
@ -1,9 +1,41 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Events */
|
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
export const coreInitialized = () => ({
|
export const initializeCore = (
|
||||||
type: ActionTypes.CORE_INITIALIZED,
|
user,
|
||||||
payload: {},
|
board,
|
||||||
|
users,
|
||||||
|
projects,
|
||||||
|
projectManagers,
|
||||||
|
boards,
|
||||||
|
boardMemberships,
|
||||||
|
labels,
|
||||||
|
lists,
|
||||||
|
cards,
|
||||||
|
cardMemberships,
|
||||||
|
cardLabels,
|
||||||
|
tasks,
|
||||||
|
attachments,
|
||||||
|
actions,
|
||||||
|
notifications,
|
||||||
|
) => ({
|
||||||
|
type: ActionTypes.CORE_INITIALIZE,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
board,
|
||||||
|
users,
|
||||||
|
projects,
|
||||||
|
projectManagers,
|
||||||
|
boards,
|
||||||
|
boardMemberships,
|
||||||
|
labels,
|
||||||
|
lists,
|
||||||
|
cards,
|
||||||
|
cardMemberships,
|
||||||
|
cardLabels,
|
||||||
|
tasks,
|
||||||
|
attachments,
|
||||||
|
actions,
|
||||||
|
notifications,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
22
client/src/actions/entry/action.js
Normal file
22
client/src/actions/entry/action.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import EntryActionTypes from '../../constants/EntryActionTypes';
|
||||||
|
|
||||||
|
export const handleActionCreate = (action) => ({
|
||||||
|
type: EntryActionTypes.ACTION_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
action,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleActionUpdate = (action) => ({
|
||||||
|
type: EntryActionTypes.ACTION_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
action,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleActionDelete = (action) => ({
|
||||||
|
type: EntryActionTypes.ACTION_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
action,
|
||||||
|
},
|
||||||
|
});
|
|
@ -7,6 +7,14 @@ export const createAttachmentInCurrentCard = (data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleAttachmentCreate = (attachment, requestId) => ({
|
||||||
|
type: EntryActionTypes.ATTACHMENT_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
attachment,
|
||||||
|
requestId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateAttachment = (id, data) => ({
|
export const updateAttachment = (id, data) => ({
|
||||||
type: EntryActionTypes.ATTACHMENT_UPDATE,
|
type: EntryActionTypes.ATTACHMENT_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -15,9 +23,23 @@ export const updateAttachment = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleAttachmentUpdate = (attachment) => ({
|
||||||
|
type: EntryActionTypes.ATTACHMENT_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
attachment,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const deleteAttachment = (id) => ({
|
export const deleteAttachment = (id) => ({
|
||||||
type: EntryActionTypes.ATTACHMENT_DELETE,
|
type: EntryActionTypes.ATTACHMENT_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleAttachmentDelete = (attachment) => ({
|
||||||
|
type: EntryActionTypes.ATTACHMENT_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
attachment,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
29
client/src/actions/entry/board-membership.js
Normal file
29
client/src/actions/entry/board-membership.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import EntryActionTypes from '../../constants/EntryActionTypes';
|
||||||
|
|
||||||
|
export const createMembershipInCurrentBoard = (data) => ({
|
||||||
|
type: EntryActionTypes.MEMBERSHIP_IN_CURRENT_BOARD_CREATE,
|
||||||
|
payload: {
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleBoardMembershipCreate = (boardMembership) => ({
|
||||||
|
type: EntryActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
boardMembership,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const deleteBoardMembership = (id) => ({
|
||||||
|
type: EntryActionTypes.BOARD_MEMBERSHIP_DELETE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleBoardMembershipDelete = (boardMembership) => ({
|
||||||
|
type: EntryActionTypes.BOARD_MEMBERSHIP_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
boardMembership,
|
||||||
|
},
|
||||||
|
});
|
|
@ -7,6 +7,13 @@ export const createBoardInCurrentProject = (data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleBoardCreate = (board) => ({
|
||||||
|
type: EntryActionTypes.BOARD_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
board,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const fetchBoard = (id) => ({
|
export const fetchBoard = (id) => ({
|
||||||
type: EntryActionTypes.BOARD_FETCH,
|
type: EntryActionTypes.BOARD_FETCH,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -22,6 +29,13 @@ export const updateBoard = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleBoardUpdate = (board) => ({
|
||||||
|
type: EntryActionTypes.BOARD_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
board,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const moveBoard = (id, index) => ({
|
export const moveBoard = (id, index) => ({
|
||||||
type: EntryActionTypes.BOARD_MOVE,
|
type: EntryActionTypes.BOARD_MOVE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -36,3 +50,10 @@ export const deleteBoard = (id) => ({
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleBoardDelete = (board) => ({
|
||||||
|
type: EntryActionTypes.BOARD_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
board,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
|
@ -8,6 +8,13 @@ export const createCard = (listId, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleCardCreate = (card) => ({
|
||||||
|
type: EntryActionTypes.CARD_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
card,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateCard = (id, data) => ({
|
export const updateCard = (id, data) => ({
|
||||||
type: EntryActionTypes.CARD_UPDATE,
|
type: EntryActionTypes.CARD_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -23,6 +30,13 @@ export const updateCurrentCard = (data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleCardUpdate = (card) => ({
|
||||||
|
type: EntryActionTypes.CARD_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
card,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const moveCard = (id, listId, index = 0) => ({
|
export const moveCard = (id, listId, index = 0) => ({
|
||||||
type: EntryActionTypes.CARD_MOVE,
|
type: EntryActionTypes.CARD_MOVE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -70,3 +84,10 @@ export const deleteCurrentCard = () => ({
|
||||||
type: EntryActionTypes.CURRENT_CARD_DELETE,
|
type: EntryActionTypes.CURRENT_CARD_DELETE,
|
||||||
payload: {},
|
payload: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleCardDelete = (card) => ({
|
||||||
|
type: EntryActionTypes.CARD_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
card,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
7
client/src/actions/entry/core.js
Normal file
7
client/src/actions/entry/core.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import EntryActionTypes from '../../constants/EntryActionTypes';
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
|
export const initializeCore = () => ({
|
||||||
|
type: EntryActionTypes.CORE_INITIALIZE,
|
||||||
|
payload: {},
|
||||||
|
});
|
|
@ -1,14 +1,18 @@
|
||||||
|
export * from './socket';
|
||||||
export * from './login';
|
export * from './login';
|
||||||
|
export * from './core';
|
||||||
export * from './modal';
|
export * from './modal';
|
||||||
export * from './user';
|
export * from './user';
|
||||||
export * from './project';
|
export * from './project';
|
||||||
export * from './project-membership';
|
export * from './project-manager';
|
||||||
export * from './board';
|
export * from './board';
|
||||||
|
export * from './board-membership';
|
||||||
export * from './label';
|
export * from './label';
|
||||||
export * from './list';
|
export * from './list';
|
||||||
export * from './card';
|
export * from './card';
|
||||||
export * from './task';
|
export * from './task';
|
||||||
export * from './attachment';
|
export * from './attachment';
|
||||||
export * from './actions';
|
export * from './actions';
|
||||||
|
export * from './action';
|
||||||
export * from './comment-action';
|
export * from './comment-action';
|
||||||
export * from './notification';
|
export * from './notification';
|
||||||
|
|
|
@ -7,6 +7,13 @@ export const createLabelInCurrentBoard = (data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleLabelCreate = (label) => ({
|
||||||
|
type: EntryActionTypes.LABEL_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateLabel = (id, data) => ({
|
export const updateLabel = (id, data) => ({
|
||||||
type: EntryActionTypes.LABEL_UPDATE,
|
type: EntryActionTypes.LABEL_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -15,6 +22,13 @@ export const updateLabel = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleLabelUpdate = (label) => ({
|
||||||
|
type: EntryActionTypes.LABEL_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const deleteLabel = (id) => ({
|
export const deleteLabel = (id) => ({
|
||||||
type: EntryActionTypes.LABEL_DELETE,
|
type: EntryActionTypes.LABEL_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -22,6 +36,13 @@ export const deleteLabel = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleLabelDelete = (label) => ({
|
||||||
|
type: EntryActionTypes.LABEL_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const addLabelToCard = (id, cardId) => ({
|
export const addLabelToCard = (id, cardId) => ({
|
||||||
type: EntryActionTypes.LABEL_TO_CARD_ADD,
|
type: EntryActionTypes.LABEL_TO_CARD_ADD,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -37,6 +58,13 @@ export const addLabelToCurrentCard = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleLabelToCardAdd = (cardLabel) => ({
|
||||||
|
type: EntryActionTypes.LABEL_TO_CARD_ADD_HANDLE,
|
||||||
|
payload: {
|
||||||
|
cardLabel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const removeLabelFromCard = (id, cardId) => ({
|
export const removeLabelFromCard = (id, cardId) => ({
|
||||||
type: EntryActionTypes.LABEL_FROM_CARD_REMOVE,
|
type: EntryActionTypes.LABEL_FROM_CARD_REMOVE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -52,6 +80,13 @@ export const removeLabelFromCurrentCard = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleLabelFromCardRemove = (cardLabel) => ({
|
||||||
|
type: EntryActionTypes.LABEL_FROM_CARD_REMOVE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
cardLabel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const addLabelToFilterInCurrentBoard = (id) => ({
|
export const addLabelToFilterInCurrentBoard = (id) => ({
|
||||||
type: EntryActionTypes.LABEL_TO_FILTER_IN_CURRENT_BOARD_ADD,
|
type: EntryActionTypes.LABEL_TO_FILTER_IN_CURRENT_BOARD_ADD,
|
||||||
payload: {
|
payload: {
|
||||||
|
|
|
@ -7,6 +7,13 @@ export const createListInCurrentBoard = (data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleListCreate = (list) => ({
|
||||||
|
type: EntryActionTypes.LIST_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
list,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateList = (id, data) => ({
|
export const updateList = (id, data) => ({
|
||||||
type: EntryActionTypes.LIST_UPDATE,
|
type: EntryActionTypes.LIST_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -15,6 +22,13 @@ export const updateList = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleListUpdate = (list) => ({
|
||||||
|
type: EntryActionTypes.LIST_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
list,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const moveList = (id, index) => ({
|
export const moveList = (id, index) => ({
|
||||||
type: EntryActionTypes.LIST_MOVE,
|
type: EntryActionTypes.LIST_MOVE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -29,3 +43,10 @@ export const deleteList = (id) => ({
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleListDelete = (list) => ({
|
||||||
|
type: EntryActionTypes.LIST_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
list,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
|
@ -22,6 +22,13 @@ export const openProjectAddModal = () => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const openProjectSettingsModal = () => ({
|
||||||
|
type: EntryActionTypes.MODAL_OPEN,
|
||||||
|
payload: {
|
||||||
|
type: ModalTypes.PROJECT_SETTINGS,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const closeModal = () => ({
|
export const closeModal = () => ({
|
||||||
type: EntryActionTypes.MODAL_CLOSE,
|
type: EntryActionTypes.MODAL_CLOSE,
|
||||||
payload: {},
|
payload: {},
|
||||||
|
|
|
@ -1,9 +1,22 @@
|
||||||
import EntryActionTypes from '../../constants/EntryActionTypes';
|
import EntryActionTypes from '../../constants/EntryActionTypes';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
export const handleNotificationCreate = (notification) => ({
|
||||||
|
type: EntryActionTypes.NOTIFICATION_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
notification,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const deleteNotification = (id) => ({
|
export const deleteNotification = (id) => ({
|
||||||
type: EntryActionTypes.NOTIFICATION_DELETE,
|
type: EntryActionTypes.NOTIFICATION_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleNotificationDelete = (notification) => ({
|
||||||
|
type: EntryActionTypes.NOTIFICATION_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
notification,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
29
client/src/actions/entry/project-manager.js
Executable file
29
client/src/actions/entry/project-manager.js
Executable file
|
@ -0,0 +1,29 @@
|
||||||
|
import EntryActionTypes from '../../constants/EntryActionTypes';
|
||||||
|
|
||||||
|
export const createManagerInCurrentProject = (data) => ({
|
||||||
|
type: EntryActionTypes.MANAGER_IN_CURRENT_PROJECT_CREATE,
|
||||||
|
payload: {
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleProjectManagerCreate = (projectManager) => ({
|
||||||
|
type: EntryActionTypes.PROJECT_MANAGER_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
projectManager,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const deleteProjectManager = (id) => ({
|
||||||
|
type: EntryActionTypes.PROJECT_MANAGER_DELETE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleProjectManagerDelete = (projectManager) => ({
|
||||||
|
type: EntryActionTypes.PROJECT_MANAGER_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
projectManager,
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,15 +0,0 @@
|
||||||
import EntryActionTypes from '../../constants/EntryActionTypes';
|
|
||||||
|
|
||||||
export const createMembershipInCurrentProject = (data) => ({
|
|
||||||
type: EntryActionTypes.MEMBERSHIP_IN_CURRENT_PROJECT_CREATE,
|
|
||||||
payload: {
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteProjectMembership = (id) => ({
|
|
||||||
type: EntryActionTypes.PROJECT_MEMBERSHIP_DELETE,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -7,6 +7,13 @@ export const createProject = (data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleProjectCreate = (project) => ({
|
||||||
|
type: EntryActionTypes.PROJECT_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
project,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateCurrentProject = (data) => ({
|
export const updateCurrentProject = (data) => ({
|
||||||
type: EntryActionTypes.CURRENT_PROJECT_UPDATE,
|
type: EntryActionTypes.CURRENT_PROJECT_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -14,6 +21,13 @@ export const updateCurrentProject = (data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleProjectUpdate = (project) => ({
|
||||||
|
type: EntryActionTypes.PROJECT_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
project,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateCurrentProjectBackgroundImage = (data) => ({
|
export const updateCurrentProjectBackgroundImage = (data) => ({
|
||||||
type: EntryActionTypes.CURRENT_PROJECT_BACKGROUND_IMAGE_UPDATE,
|
type: EntryActionTypes.CURRENT_PROJECT_BACKGROUND_IMAGE_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -25,3 +39,10 @@ export const deleteCurrentProject = () => ({
|
||||||
type: EntryActionTypes.CURRENT_PROJECT_DELETE,
|
type: EntryActionTypes.CURRENT_PROJECT_DELETE,
|
||||||
payload: {},
|
payload: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleProjectDelete = (project) => ({
|
||||||
|
type: EntryActionTypes.PROJECT_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
project,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
11
client/src/actions/entry/socket.js
Normal file
11
client/src/actions/entry/socket.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import EntryActionTypes from '../../constants/EntryActionTypes';
|
||||||
|
|
||||||
|
export const handleSocketDisconnect = () => ({
|
||||||
|
type: EntryActionTypes.SOCKET_DISCONNECT_HANDLE,
|
||||||
|
payload: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleSocketReconnect = () => ({
|
||||||
|
type: EntryActionTypes.SOCKET_RECONNECT_HANDLE,
|
||||||
|
payload: {},
|
||||||
|
});
|
|
@ -7,6 +7,13 @@ export const createTaskInCurrentCard = (data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleTaskCreate = (task) => ({
|
||||||
|
type: EntryActionTypes.TASK_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
task,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateTask = (id, data) => ({
|
export const updateTask = (id, data) => ({
|
||||||
type: EntryActionTypes.TASK_UPDATE,
|
type: EntryActionTypes.TASK_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -15,9 +22,23 @@ export const updateTask = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleTaskUpdate = (task) => ({
|
||||||
|
type: EntryActionTypes.TASK_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
task,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const deleteTask = (id) => ({
|
export const deleteTask = (id) => ({
|
||||||
type: EntryActionTypes.TASK_DELETE,
|
type: EntryActionTypes.TASK_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleTaskDelete = (task) => ({
|
||||||
|
type: EntryActionTypes.TASK_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
task,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
|
@ -7,6 +7,13 @@ export const createUser = (data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleUserCreate = (user) => ({
|
||||||
|
type: EntryActionTypes.USER_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const clearUserCreateError = () => ({
|
export const clearUserCreateError = () => ({
|
||||||
type: EntryActionTypes.USER_CREATE_ERROR_CLEAR,
|
type: EntryActionTypes.USER_CREATE_ERROR_CLEAR,
|
||||||
payload: {},
|
payload: {},
|
||||||
|
@ -27,6 +34,13 @@ export const updateCurrentUser = (data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleUserUpdate = (user) => ({
|
||||||
|
type: EntryActionTypes.USER_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateCurrentUserEmail = (data) => ({
|
export const updateCurrentUserEmail = (data) => ({
|
||||||
type: EntryActionTypes.CURRENT_USER_EMAIL_UPDATE,
|
type: EntryActionTypes.CURRENT_USER_EMAIL_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -77,6 +91,13 @@ export const deleteUser = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleUserDelete = (user) => ({
|
||||||
|
type: EntryActionTypes.USER_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const addUserToCard = (id, cardId) => ({
|
export const addUserToCard = (id, cardId) => ({
|
||||||
type: EntryActionTypes.USER_TO_CARD_ADD,
|
type: EntryActionTypes.USER_TO_CARD_ADD,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -92,6 +113,13 @@ export const addUserToCurrentCard = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleUserToCardAdd = (cardMembership) => ({
|
||||||
|
type: EntryActionTypes.USER_TO_CARD_ADD_HANDLE,
|
||||||
|
payload: {
|
||||||
|
cardMembership,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const removeUserFromCard = (id, cardId) => ({
|
export const removeUserFromCard = (id, cardId) => ({
|
||||||
type: EntryActionTypes.USER_FROM_CARD_REMOVE,
|
type: EntryActionTypes.USER_FROM_CARD_REMOVE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -107,6 +135,13 @@ export const removeUserFromCurrentCard = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const handleUserFromCardRemove = (cardMembership) => ({
|
||||||
|
type: EntryActionTypes.USER_FROM_CARD_REMOVE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
cardMembership,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const addUserToFilterInCurrentBoard = (id) => ({
|
export const addUserToFilterInCurrentBoard = (id) => ({
|
||||||
type: EntryActionTypes.USER_TO_FILTER_IN_CURRENT_BOARD_ADD,
|
type: EntryActionTypes.USER_TO_FILTER_IN_CURRENT_BOARD_ADD,
|
||||||
payload: {
|
payload: {
|
||||||
|
|
|
@ -1,22 +1,19 @@
|
||||||
|
export * from './router';
|
||||||
export * from './socket';
|
export * from './socket';
|
||||||
export * from './login';
|
export * from './login';
|
||||||
export * from './core';
|
export * from './core';
|
||||||
export * from './modal';
|
export * from './modal';
|
||||||
export * from './users';
|
|
||||||
export * from './user';
|
export * from './user';
|
||||||
export * from './projects';
|
|
||||||
export * from './project';
|
export * from './project';
|
||||||
export * from './project-membership';
|
export * from './project-manager';
|
||||||
export * from './board';
|
export * from './board';
|
||||||
|
export * from './board-membership';
|
||||||
export * from './label';
|
export * from './label';
|
||||||
export * from './list';
|
export * from './list';
|
||||||
export * from './card';
|
export * from './card';
|
||||||
export * from './card-membership';
|
|
||||||
export * from './card-label';
|
|
||||||
export * from './task';
|
export * from './task';
|
||||||
export * from './attachment';
|
export * from './attachment';
|
||||||
export * from './actions';
|
export * from './actions';
|
||||||
export * from './action';
|
export * from './action';
|
||||||
export * from './comment-action';
|
export * from './comment-action';
|
||||||
export * from './notifications';
|
|
||||||
export * from './notification';
|
export * from './notification';
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
export const createLabel = (label) => ({
|
export const createLabel = (label) => ({
|
||||||
type: ActionTypes.LABEL_CREATE,
|
type: ActionTypes.LABEL_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -9,6 +7,29 @@ export const createLabel = (label) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
createLabel.success = (localId, label) => ({
|
||||||
|
type: ActionTypes.LABEL_CREATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createLabel.failure = (localId, error) => ({
|
||||||
|
type: ActionTypes.LABEL_CREATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleLabelCreate = (label) => ({
|
||||||
|
type: ActionTypes.LABEL_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateLabel = (id, data) => ({
|
export const updateLabel = (id, data) => ({
|
||||||
type: ActionTypes.LABEL_UPDATE,
|
type: ActionTypes.LABEL_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -17,6 +38,28 @@ export const updateLabel = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateLabel.success = (label) => ({
|
||||||
|
type: ActionTypes.LABEL_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateLabel.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.LABEL_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleLabelUpdate = (label) => ({
|
||||||
|
type: ActionTypes.LABEL_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const deleteLabel = (id) => ({
|
export const deleteLabel = (id) => ({
|
||||||
type: ActionTypes.LABEL_DELETE,
|
type: ActionTypes.LABEL_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -24,6 +67,28 @@ export const deleteLabel = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
deleteLabel.success = (label) => ({
|
||||||
|
type: ActionTypes.LABEL_DELETE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteLabel.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.LABEL_DELETE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleLabelDelete = (label) => ({
|
||||||
|
type: ActionTypes.LABEL_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const addLabelToCard = (id, cardId) => ({
|
export const addLabelToCard = (id, cardId) => ({
|
||||||
type: ActionTypes.LABEL_TO_CARD_ADD,
|
type: ActionTypes.LABEL_TO_CARD_ADD,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -32,6 +97,29 @@ export const addLabelToCard = (id, cardId) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addLabelToCard.success = (cardLabel) => ({
|
||||||
|
type: ActionTypes.LABEL_TO_CARD_ADD__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
cardLabel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
addLabelToCard.failure = (id, cardId, error) => ({
|
||||||
|
type: ActionTypes.LABEL_TO_CARD_ADD__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
cardId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleLabelToCardAdd = (cardLabel) => ({
|
||||||
|
type: ActionTypes.LABEL_TO_CARD_ADD_HANDLE,
|
||||||
|
payload: {
|
||||||
|
cardLabel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const removeLabelFromCard = (id, cardId) => ({
|
export const removeLabelFromCard = (id, cardId) => ({
|
||||||
type: ActionTypes.LABEL_FROM_CARD_REMOVE,
|
type: ActionTypes.LABEL_FROM_CARD_REMOVE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -40,6 +128,29 @@ export const removeLabelFromCard = (id, cardId) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
removeLabelFromCard.success = (cardLabel) => ({
|
||||||
|
type: ActionTypes.LABEL_FROM_CARD_REMOVE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
cardLabel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
removeLabelFromCard.failure = (id, cardId, error) => ({
|
||||||
|
type: ActionTypes.LABEL_FROM_CARD_REMOVE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
cardId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleLabelFromCardRemove = (cardLabel) => ({
|
||||||
|
type: ActionTypes.LABEL_FROM_CARD_REMOVE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
cardLabel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const addLabelToBoardFilter = (id, boardId) => ({
|
export const addLabelToBoardFilter = (id, boardId) => ({
|
||||||
type: ActionTypes.LABEL_TO_BOARD_FILTER_ADD,
|
type: ActionTypes.LABEL_TO_BOARD_FILTER_ADD,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -55,95 +166,3 @@ export const removeLabelFromBoardFilter = (id, boardId) => ({
|
||||||
boardId,
|
boardId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Events */
|
|
||||||
|
|
||||||
export const createLabelRequested = (localId, data) => ({
|
|
||||||
type: ActionTypes.LABEL_CREATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createLabelSucceeded = (localId, label) => ({
|
|
||||||
type: ActionTypes.LABEL_CREATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
label,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createLabelFailed = (localId, error) => ({
|
|
||||||
type: ActionTypes.LABEL_CREATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createLabelReceived = (label) => ({
|
|
||||||
type: ActionTypes.LABEL_CREATE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
label,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateLabelRequested = (id, data) => ({
|
|
||||||
type: ActionTypes.LABEL_UPDATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateLabelSucceeded = (label) => ({
|
|
||||||
type: ActionTypes.LABEL_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
label,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateLabelFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.LABEL_UPDATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateLabelReceived = (label) => ({
|
|
||||||
type: ActionTypes.LABEL_UPDATE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
label,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteLabelRequested = (id) => ({
|
|
||||||
type: ActionTypes.LABEL_DELETE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteLabelSucceeded = (label) => ({
|
|
||||||
type: ActionTypes.LABEL_DELETE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
label,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteLabelFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.LABEL_DELETE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteLabelReceived = (label) => ({
|
|
||||||
type: ActionTypes.LABEL_DELETE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
label,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
export const createList = (list) => ({
|
export const createList = (list) => ({
|
||||||
type: ActionTypes.LIST_CREATE,
|
type: ActionTypes.LIST_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -9,6 +7,29 @@ export const createList = (list) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
createList.success = (localId, list) => ({
|
||||||
|
type: ActionTypes.LIST_CREATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
list,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createList.failure = (localId, error) => ({
|
||||||
|
type: ActionTypes.LIST_CREATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleListCreate = (list) => ({
|
||||||
|
type: ActionTypes.LIST_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
list,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateList = (id, data) => ({
|
export const updateList = (id, data) => ({
|
||||||
type: ActionTypes.LIST_UPDATE,
|
type: ActionTypes.LIST_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -17,6 +38,28 @@ export const updateList = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateList.success = (list) => ({
|
||||||
|
type: ActionTypes.LIST_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
list,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateList.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.LIST_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleListUpdate = (list) => ({
|
||||||
|
type: ActionTypes.LIST_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
list,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const deleteList = (id) => ({
|
export const deleteList = (id) => ({
|
||||||
type: ActionTypes.LIST_DELETE,
|
type: ActionTypes.LIST_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -24,93 +67,23 @@ export const deleteList = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Events */
|
deleteList.success = (list) => ({
|
||||||
|
type: ActionTypes.LIST_DELETE__SUCCESS,
|
||||||
export const createListRequested = (localId, data) => ({
|
|
||||||
type: ActionTypes.LIST_CREATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createListSucceeded = (localId, list) => ({
|
|
||||||
type: ActionTypes.LIST_CREATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
list,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createListFailed = (localId, error) => ({
|
|
||||||
type: ActionTypes.LIST_CREATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createListReceived = (list) => ({
|
|
||||||
type: ActionTypes.LIST_CREATE_RECEIVED,
|
|
||||||
payload: {
|
payload: {
|
||||||
list,
|
list,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateListRequested = (id, data) => ({
|
deleteList.failure = (id, error) => ({
|
||||||
type: ActionTypes.LIST_UPDATE_REQUESTED,
|
type: ActionTypes.LIST_DELETE__FAILURE,
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateListSucceeded = (list) => ({
|
|
||||||
type: ActionTypes.LIST_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
list,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateListFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.LIST_UPDATE_FAILED,
|
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
error,
|
error,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateListReceived = (list) => ({
|
export const handleListDelete = (list) => ({
|
||||||
type: ActionTypes.LIST_UPDATE_RECEIVED,
|
type: ActionTypes.LIST_DELETE_HANDLE,
|
||||||
payload: {
|
|
||||||
list,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteListRequested = (id) => ({
|
|
||||||
type: ActionTypes.LIST_DELETE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteListSucceeded = (list) => ({
|
|
||||||
type: ActionTypes.LIST_DELETE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
list,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteListFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.LIST_DELETE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteListReceived = (list) => ({
|
|
||||||
type: ActionTypes.LIST_DELETE_RECEIVED,
|
|
||||||
payload: {
|
payload: {
|
||||||
list,
|
list,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
export const authenticate = (data) => ({
|
export const authenticate = (data) => ({
|
||||||
type: ActionTypes.AUTHENTICATE,
|
type: ActionTypes.AUTHENTICATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -9,6 +7,20 @@ export const authenticate = (data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
authenticate.success = (accessToken) => ({
|
||||||
|
type: ActionTypes.AUTHENTICATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
accessToken,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
authenticate.failure = (error) => ({
|
||||||
|
type: ActionTypes.AUTHENTICATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const clearAuthenticateError = () => ({
|
export const clearAuthenticateError = () => ({
|
||||||
type: ActionTypes.AUTHENTICATE_ERROR_CLEAR,
|
type: ActionTypes.AUTHENTICATE_ERROR_CLEAR,
|
||||||
payload: {},
|
payload: {},
|
||||||
|
@ -18,26 +30,3 @@ export const logout = () => ({
|
||||||
type: ActionTypes.LOGOUT,
|
type: ActionTypes.LOGOUT,
|
||||||
payload: {},
|
payload: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Events */
|
|
||||||
|
|
||||||
export const authenticateRequested = (data) => ({
|
|
||||||
type: ActionTypes.AUTHENTICATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const authenticateSucceeded = (accessToken) => ({
|
|
||||||
type: ActionTypes.AUTHENTICATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
accessToken,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const authenticateFailed = (error) => ({
|
|
||||||
type: ActionTypes.AUTHENTICATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
export const openModal = (type) => ({
|
export const openModal = (type) => ({
|
||||||
type: ActionTypes.MODAL_OPEN,
|
type: ActionTypes.MODAL_OPEN,
|
||||||
payload: {
|
payload: {
|
||||||
|
|
|
@ -1,19 +1,39 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Events */
|
export const handleNotificationCreate = (notification, users, cards, actions) => ({
|
||||||
|
type: ActionTypes.NOTIFICATION_CREATE_HANDLE,
|
||||||
export const createNotificationReceived = (notification, user, card, action) => ({
|
|
||||||
type: ActionTypes.NOTIFICATION_CREATE_RECEIVED,
|
|
||||||
payload: {
|
payload: {
|
||||||
notification,
|
notification,
|
||||||
user,
|
users,
|
||||||
card,
|
cards,
|
||||||
action,
|
actions,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteNotificationReceived = (notification) => ({
|
export const deleteNotification = (id) => ({
|
||||||
type: ActionTypes.NOTIFICATION_DELETE_RECEIVED,
|
type: ActionTypes.NOTIFICATION_DELETE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteNotification.success = (notification) => ({
|
||||||
|
type: ActionTypes.NOTIFICATION_DELETE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
notification,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteNotification.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.NOTIFICATION_DELETE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleNotificationDelete = (notification) => ({
|
||||||
|
type: ActionTypes.NOTIFICATION_DELETE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
notification,
|
notification,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
export const deleteNotifications = (ids) => ({
|
|
||||||
type: ActionTypes.NOTIFICATIONS_DELETE,
|
|
||||||
payload: {
|
|
||||||
ids,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Events */
|
|
||||||
|
|
||||||
export const fetchNotificationsRequested = () => ({
|
|
||||||
type: ActionTypes.NOTIFICATIONS_FETCH_REQUESTED,
|
|
||||||
payload: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchNotificationsSucceeded = (notifications, users, cards, actions) => ({
|
|
||||||
type: ActionTypes.NOTIFICATIONS_FETCH_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
notifications,
|
|
||||||
users,
|
|
||||||
cards,
|
|
||||||
actions,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchNotificationsFailed = (error) => ({
|
|
||||||
type: ActionTypes.NOTIFICATIONS_FETCH_FAILED,
|
|
||||||
payload: {
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteNotificationsRequested = (ids) => ({
|
|
||||||
type: ActionTypes.NOTIFICATIONS_DELETE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
ids,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteNotificationsSucceeded = (notifications) => ({
|
|
||||||
type: ActionTypes.NOTIFICATIONS_DELETE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
notifications,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteNotificationsFailed = (ids, error) => ({
|
|
||||||
type: ActionTypes.NOTIFICATIONS_DELETE_FAILED,
|
|
||||||
payload: {
|
|
||||||
ids,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
101
client/src/actions/project-manager.js
Normal file
101
client/src/actions/project-manager.js
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
|
export const createProjectManager = (projectManager) => ({
|
||||||
|
type: ActionTypes.PROJECT_MANAGER_CREATE,
|
||||||
|
payload: {
|
||||||
|
projectManager,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createProjectManager.success = (localId, projectManager) => ({
|
||||||
|
type: ActionTypes.PROJECT_MANAGER_CREATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
projectManager,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createProjectManager.failure = (localId, error) => ({
|
||||||
|
type: ActionTypes.PROJECT_MANAGER_CREATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleProjectManagerCreate = (
|
||||||
|
projectManager,
|
||||||
|
project,
|
||||||
|
board,
|
||||||
|
users,
|
||||||
|
projectManagers,
|
||||||
|
boards,
|
||||||
|
boardMemberships,
|
||||||
|
labels,
|
||||||
|
lists,
|
||||||
|
cards,
|
||||||
|
cardMemberships,
|
||||||
|
cardLabels,
|
||||||
|
tasks,
|
||||||
|
attachments,
|
||||||
|
) => ({
|
||||||
|
type: ActionTypes.PROJECT_MANAGER_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
projectManager,
|
||||||
|
project,
|
||||||
|
board,
|
||||||
|
users,
|
||||||
|
projectManagers,
|
||||||
|
boards,
|
||||||
|
boardMemberships,
|
||||||
|
labels,
|
||||||
|
lists,
|
||||||
|
cards,
|
||||||
|
cardMemberships,
|
||||||
|
cardLabels,
|
||||||
|
tasks,
|
||||||
|
attachments,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
handleProjectManagerCreate.fetchProject = (id, currentUserId, currentBoardId) => ({
|
||||||
|
type: ActionTypes.PROJECT_MANAGER_CREATE_HANDLE__PROJECT_FETCH,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
currentUserId,
|
||||||
|
currentBoardId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const deleteProjectManager = (id, isCurrentUser, isCurrentProject) => ({
|
||||||
|
type: ActionTypes.PROJECT_MANAGER_DELETE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
isCurrentUser,
|
||||||
|
isCurrentProject,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteProjectManager.success = (projectManager) => ({
|
||||||
|
type: ActionTypes.PROJECT_MANAGER_DELETE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
projectManager,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteProjectManager.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.PROJECT_MANAGER_DELETE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleProjectManagerDelete = (projectManager, isCurrentUser, isCurrentProject) => ({
|
||||||
|
type: ActionTypes.PROJECT_MANAGER_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
projectManager,
|
||||||
|
isCurrentUser,
|
||||||
|
isCurrentProject,
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,80 +0,0 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
export const createProjectMembership = (projectMembership) => ({
|
|
||||||
type: ActionTypes.PROJECT_MEMBERSHIP_CREATE,
|
|
||||||
payload: {
|
|
||||||
projectMembership,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteProjectMembership = (id) => ({
|
|
||||||
type: ActionTypes.PROJECT_MEMBERSHIP_DELETE,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Events */
|
|
||||||
|
|
||||||
export const createProjectMembershipRequested = (localId, data) => ({
|
|
||||||
type: ActionTypes.PROJECT_MEMBERSHIP_CREATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createProjectMembershipSucceeded = (localId, projectMembership) => ({
|
|
||||||
type: ActionTypes.PROJECT_MEMBERSHIP_CREATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
projectMembership,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createProjectMembershipFailed = (localId, error) => ({
|
|
||||||
type: ActionTypes.PROJECT_MEMBERSHIP_CREATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createProjectMembershipReceived = (projectMembership, user) => ({
|
|
||||||
type: ActionTypes.PROJECT_MEMBERSHIP_CREATE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
projectMembership,
|
|
||||||
user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteProjectMembershipRequested = (id) => ({
|
|
||||||
type: ActionTypes.PROJECT_MEMBERSHIP_DELETE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteProjectMembershipSucceeded = (projectMembership) => ({
|
|
||||||
type: ActionTypes.PROJECT_MEMBERSHIP_DELETE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
projectMembership,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteProjectMembershipFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.PROJECT_MEMBERSHIP_DELETE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteProjectMembershipReceived = (projectMembership) => ({
|
|
||||||
type: ActionTypes.PROJECT_MEMBERSHIP_DELETE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
projectMembership,
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,7 +1,5 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
export const createProject = (data) => ({
|
export const createProject = (data) => ({
|
||||||
type: ActionTypes.PROJECT_CREATE,
|
type: ActionTypes.PROJECT_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -9,6 +7,32 @@ export const createProject = (data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
createProject.success = (project, projectManagers) => ({
|
||||||
|
type: ActionTypes.PROJECT_CREATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
project,
|
||||||
|
projectManagers,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createProject.failure = (error) => ({
|
||||||
|
type: ActionTypes.PROJECT_CREATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleProjectCreate = (project, users, projectManagers, boards, boardMemberships) => ({
|
||||||
|
type: ActionTypes.PROJECT_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
project,
|
||||||
|
users,
|
||||||
|
projectManagers,
|
||||||
|
boards,
|
||||||
|
boardMemberships,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateProject = (id, data) => ({
|
export const updateProject = (id, data) => ({
|
||||||
type: ActionTypes.PROJECT_UPDATE,
|
type: ActionTypes.PROJECT_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -17,6 +41,50 @@ export const updateProject = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateProject.success = (project) => ({
|
||||||
|
type: ActionTypes.PROJECT_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
project,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateProject.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.PROJECT_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleProjectUpdate = (project) => ({
|
||||||
|
type: ActionTypes.PROJECT_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
project,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const updateProjectBackgroundImage = (id) => ({
|
||||||
|
type: ActionTypes.PROJECT_BACKGROUND_IMAGE_UPDATE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateProjectBackgroundImage.success = (project) => ({
|
||||||
|
type: ActionTypes.PROJECT_BACKGROUND_IMAGE_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
project,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateProjectBackgroundImage.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.PROJECT_BACKGROUND_IMAGE_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const deleteProject = (id) => ({
|
export const deleteProject = (id) => ({
|
||||||
type: ActionTypes.PROJECT_DELETE,
|
type: ActionTypes.PROJECT_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -24,118 +92,23 @@ export const deleteProject = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Events */
|
deleteProject.success = (project) => ({
|
||||||
|
type: ActionTypes.PROJECT_DELETE__SUCCESS,
|
||||||
export const createProjectRequested = (data) => ({
|
|
||||||
type: ActionTypes.PROJECT_CREATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createProjectSucceeded = (project, users, projectMemberships, boards) => ({
|
|
||||||
type: ActionTypes.PROJECT_CREATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
project,
|
|
||||||
users,
|
|
||||||
projectMemberships,
|
|
||||||
boards,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createProjectFailed = (error) => ({
|
|
||||||
type: ActionTypes.PROJECT_CREATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createProjectReceived = (project, users, projectMemberships, boards) => ({
|
|
||||||
type: ActionTypes.PROJECT_CREATE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
project,
|
|
||||||
users,
|
|
||||||
projectMemberships,
|
|
||||||
boards,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateProjectRequested = (id, data) => ({
|
|
||||||
type: ActionTypes.PROJECT_UPDATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateProjectSucceeded = (project) => ({
|
|
||||||
type: ActionTypes.PROJECT_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
payload: {
|
||||||
project,
|
project,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateProjectFailed = (id, error) => ({
|
deleteProject.failure = (id, error) => ({
|
||||||
type: ActionTypes.PROJECT_UPDATE_FAILED,
|
type: ActionTypes.PROJECT_DELETE__FAILURE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
error,
|
error,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateProjectReceived = (project) => ({
|
export const handleProjectDelete = (project) => ({
|
||||||
type: ActionTypes.PROJECT_UPDATE_RECEIVED,
|
type: ActionTypes.PROJECT_DELETE_HANDLE,
|
||||||
payload: {
|
|
||||||
project,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateProjectBackgroundImageRequested = (id) => ({
|
|
||||||
type: ActionTypes.PROJECT_BACKGROUND_IMAGE_UPDATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateProjectBackgroundImageSucceeded = (project) => ({
|
|
||||||
type: ActionTypes.PROJECT_BACKGROUND_IMAGE_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
project,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateProjectBackgroundImageFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.PROJECT_BACKGROUND_IMAGE_UPDATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteProjectRequested = (id) => ({
|
|
||||||
type: ActionTypes.PROJECT_DELETE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteProjectSucceeded = (project) => ({
|
|
||||||
type: ActionTypes.PROJECT_DELETE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
project,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteProjectFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.PROJECT_DELETE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteProjectReceived = (project) => ({
|
|
||||||
type: ActionTypes.PROJECT_DELETE_RECEIVED,
|
|
||||||
payload: {
|
payload: {
|
||||||
project,
|
project,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
|
||||||
|
|
||||||
/* Events */
|
|
||||||
|
|
||||||
export const fetchProjectsRequested = () => ({
|
|
||||||
type: ActionTypes.PROJECTS_FETCH_REQUESTED,
|
|
||||||
payload: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchProjectsSucceeded = (projects, users, projectMemberships, boards) => ({
|
|
||||||
type: ActionTypes.PROJECTS_FETCH_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
projects,
|
|
||||||
users,
|
|
||||||
projectMemberships,
|
|
||||||
boards,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchProjectsFailed = (error) => ({
|
|
||||||
type: ActionTypes.PROJECTS_FETCH_FAILED,
|
|
||||||
payload: {
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
40
client/src/actions/router.js
Normal file
40
client/src/actions/router.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
|
export const handleLocationChange = (
|
||||||
|
board,
|
||||||
|
users,
|
||||||
|
projects,
|
||||||
|
boardMemberships,
|
||||||
|
labels,
|
||||||
|
lists,
|
||||||
|
cards,
|
||||||
|
cardMemberships,
|
||||||
|
cardLabels,
|
||||||
|
tasks,
|
||||||
|
attachments,
|
||||||
|
notifications,
|
||||||
|
) => ({
|
||||||
|
type: ActionTypes.LOCATION_CHANGE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
board,
|
||||||
|
users,
|
||||||
|
projects,
|
||||||
|
boardMemberships,
|
||||||
|
labels,
|
||||||
|
lists,
|
||||||
|
cards,
|
||||||
|
cardMemberships,
|
||||||
|
cardLabels,
|
||||||
|
tasks,
|
||||||
|
attachments,
|
||||||
|
notifications,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
handleLocationChange.fetchBoard = (id) => ({
|
||||||
|
type: ActionTypes.LOCATION_CHANGE_HANDLE__BOARD_FETCH,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,18 +1,53 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
import SocketStatuses from '../constants/SocketStatuses';
|
|
||||||
|
|
||||||
/* Events */
|
export const handleSocketDisconnect = () => ({
|
||||||
|
type: ActionTypes.SOCKET_DISCONNECT_HANDLE,
|
||||||
|
payload: {},
|
||||||
|
});
|
||||||
|
|
||||||
export const socketDisconnected = () => ({
|
export const handleSocketReconnect = (
|
||||||
type: ActionTypes.SOCKET_STATUS_CHANGED,
|
user,
|
||||||
|
board,
|
||||||
|
users,
|
||||||
|
projects,
|
||||||
|
projectManagers,
|
||||||
|
boards,
|
||||||
|
boardMemberships,
|
||||||
|
labels,
|
||||||
|
lists,
|
||||||
|
cards,
|
||||||
|
cardMemberships,
|
||||||
|
cardLabels,
|
||||||
|
tasks,
|
||||||
|
attachments,
|
||||||
|
actions,
|
||||||
|
notifications,
|
||||||
|
) => ({
|
||||||
|
type: ActionTypes.SOCKET_RECONNECT_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
status: SocketStatuses.DISCONNECTED,
|
user,
|
||||||
|
board,
|
||||||
|
users,
|
||||||
|
projects,
|
||||||
|
projectManagers,
|
||||||
|
boards,
|
||||||
|
boardMemberships,
|
||||||
|
labels,
|
||||||
|
lists,
|
||||||
|
cards,
|
||||||
|
cardMemberships,
|
||||||
|
cardLabels,
|
||||||
|
tasks,
|
||||||
|
attachments,
|
||||||
|
actions,
|
||||||
|
notifications,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const socketReconnected = () => ({
|
handleSocketReconnect.fetchCore = (currentUserId, currentBoardId) => ({
|
||||||
type: ActionTypes.SOCKET_STATUS_CHANGED,
|
type: ActionTypes.SOCKET_RECONNECT_HANDLE__CORE_FETCH,
|
||||||
payload: {
|
payload: {
|
||||||
status: SocketStatuses.RECONNECTED,
|
currentUserId,
|
||||||
|
currentBoardId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
export const createTask = (task) => ({
|
export const createTask = (task) => ({
|
||||||
type: ActionTypes.TASK_CREATE,
|
type: ActionTypes.TASK_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -9,6 +7,29 @@ export const createTask = (task) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
createTask.success = (localId, task) => ({
|
||||||
|
type: ActionTypes.TASK_CREATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
task,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createTask.failure = (localId, error) => ({
|
||||||
|
type: ActionTypes.TASK_CREATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleTaskCreate = (task) => ({
|
||||||
|
type: ActionTypes.TASK_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
task,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const updateTask = (id, data) => ({
|
export const updateTask = (id, data) => ({
|
||||||
type: ActionTypes.TASK_UPDATE,
|
type: ActionTypes.TASK_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -17,6 +38,28 @@ export const updateTask = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateTask.success = (task) => ({
|
||||||
|
type: ActionTypes.TASK_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
task,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateTask.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.TASK_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleTaskUpdate = (task) => ({
|
||||||
|
type: ActionTypes.TASK_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
task,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const deleteTask = (id) => ({
|
export const deleteTask = (id) => ({
|
||||||
type: ActionTypes.TASK_DELETE,
|
type: ActionTypes.TASK_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -24,93 +67,23 @@ export const deleteTask = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Events */
|
deleteTask.success = (task) => ({
|
||||||
|
type: ActionTypes.TASK_DELETE__SUCCESS,
|
||||||
export const createTaskRequested = (localId, data) => ({
|
|
||||||
type: ActionTypes.TASK_CREATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createTaskSucceeded = (localId, task) => ({
|
|
||||||
type: ActionTypes.TASK_CREATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
task,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createTaskFailed = (localId, error) => ({
|
|
||||||
type: ActionTypes.TASK_CREATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
localId,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createTaskReceived = (task) => ({
|
|
||||||
type: ActionTypes.TASK_CREATE_RECEIVED,
|
|
||||||
payload: {
|
payload: {
|
||||||
task,
|
task,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateTaskRequested = (id, data) => ({
|
deleteTask.failure = (id, error) => ({
|
||||||
type: ActionTypes.TASK_UPDATE_REQUESTED,
|
type: ActionTypes.TASK_DELETE__FAILURE,
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateTaskSucceeded = (task) => ({
|
|
||||||
type: ActionTypes.TASK_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
task,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateTaskFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.TASK_UPDATE_FAILED,
|
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
error,
|
error,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateTaskReceived = (task) => ({
|
export const handleTaskDelete = (task) => ({
|
||||||
type: ActionTypes.TASK_UPDATE_RECEIVED,
|
type: ActionTypes.TASK_DELETE_HANDLE,
|
||||||
payload: {
|
|
||||||
task,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteTaskRequested = (id) => ({
|
|
||||||
type: ActionTypes.TASK_DELETE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteTaskSucceeded = (task) => ({
|
|
||||||
type: ActionTypes.TASK_DELETE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
task,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteTaskFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.TASK_DELETE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteTaskReceived = (task) => ({
|
|
||||||
type: ActionTypes.TASK_DELETE_RECEIVED,
|
|
||||||
payload: {
|
payload: {
|
||||||
task,
|
task,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
export const createUser = (data) => ({
|
export const createUser = (data) => ({
|
||||||
type: ActionTypes.USER_CREATE,
|
type: ActionTypes.USER_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -9,6 +7,27 @@ export const createUser = (data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
createUser.success = (user) => ({
|
||||||
|
type: ActionTypes.USER_CREATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createUser.failure = (error) => ({
|
||||||
|
type: ActionTypes.USER_CREATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleUserCreate = (user) => ({
|
||||||
|
type: ActionTypes.USER_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const clearUserCreateError = () => ({
|
export const clearUserCreateError = () => ({
|
||||||
type: ActionTypes.USER_CREATE_ERROR_CLEAR,
|
type: ActionTypes.USER_CREATE_ERROR_CLEAR,
|
||||||
payload: {},
|
payload: {},
|
||||||
|
@ -22,6 +41,53 @@ export const updateUser = (id, data) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateUser.success = (user) => ({
|
||||||
|
type: ActionTypes.USER_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateUser.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.USER_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleUserUpdate = (user, users, isCurrent) => ({
|
||||||
|
type: ActionTypes.USER_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
users,
|
||||||
|
isCurrent,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const updateUserEmail = (id, data) => ({
|
||||||
|
type: ActionTypes.USER_EMAIL_UPDATE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateUserEmail.success = (user) => ({
|
||||||
|
type: ActionTypes.USER_EMAIL_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateUserEmail.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.USER_EMAIL_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const clearUserEmailUpdateError = (id) => ({
|
export const clearUserEmailUpdateError = (id) => ({
|
||||||
type: ActionTypes.USER_EMAIL_UPDATE_ERROR_CLEAR,
|
type: ActionTypes.USER_EMAIL_UPDATE_ERROR_CLEAR,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -29,6 +95,29 @@ export const clearUserEmailUpdateError = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const updateUserPassword = (id, data) => ({
|
||||||
|
type: ActionTypes.USER_PASSWORD_UPDATE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateUserPassword.success = (user) => ({
|
||||||
|
type: ActionTypes.USER_PASSWORD_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateUserPassword.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.USER_PASSWORD_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const clearUserPasswordUpdateError = (id) => ({
|
export const clearUserPasswordUpdateError = (id) => ({
|
||||||
type: ActionTypes.USER_PASSWORD_UPDATE_ERROR_CLEAR,
|
type: ActionTypes.USER_PASSWORD_UPDATE_ERROR_CLEAR,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -36,6 +125,29 @@ export const clearUserPasswordUpdateError = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const updateUserUsername = (id, data) => ({
|
||||||
|
type: ActionTypes.USER_USERNAME_UPDATE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateUserUsername.success = (user) => ({
|
||||||
|
type: ActionTypes.USER_USERNAME_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateUserUsername.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.USER_USERNAME_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const clearUserUsernameUpdateError = (id) => ({
|
export const clearUserUsernameUpdateError = (id) => ({
|
||||||
type: ActionTypes.USER_USERNAME_UPDATE_ERROR_CLEAR,
|
type: ActionTypes.USER_USERNAME_UPDATE_ERROR_CLEAR,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -43,6 +155,28 @@ export const clearUserUsernameUpdateError = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const updateUserAvatar = (id) => ({
|
||||||
|
type: ActionTypes.USER_AVATAR_UPDATE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateUserAvatar.success = (user) => ({
|
||||||
|
type: ActionTypes.USER_AVATAR_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateUserAvatar.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.USER_AVATAR_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const deleteUser = (id) => ({
|
export const deleteUser = (id) => ({
|
||||||
type: ActionTypes.USER_DELETE,
|
type: ActionTypes.USER_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -50,6 +184,28 @@ export const deleteUser = (id) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
deleteUser.success = (user) => ({
|
||||||
|
type: ActionTypes.USER_DELETE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteUser.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.USER_DELETE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleUserDelete = (user) => ({
|
||||||
|
type: ActionTypes.USER_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const addUserToCard = (id, cardId, isCurrent) => ({
|
export const addUserToCard = (id, cardId, isCurrent) => ({
|
||||||
type: ActionTypes.USER_TO_CARD_ADD,
|
type: ActionTypes.USER_TO_CARD_ADD,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -59,6 +215,29 @@ export const addUserToCard = (id, cardId, isCurrent) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addUserToCard.success = (cardMembership) => ({
|
||||||
|
type: ActionTypes.USER_TO_CARD_ADD__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
cardMembership,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
addUserToCard.failure = (id, cardId, error) => ({
|
||||||
|
type: ActionTypes.USER_TO_CARD_ADD__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
cardId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleUserToCardAdd = (cardMembership) => ({
|
||||||
|
type: ActionTypes.USER_TO_CARD_ADD_HANDLE,
|
||||||
|
payload: {
|
||||||
|
cardMembership,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const removeUserFromCard = (id, cardId) => ({
|
export const removeUserFromCard = (id, cardId) => ({
|
||||||
type: ActionTypes.USER_FROM_CARD_REMOVE,
|
type: ActionTypes.USER_FROM_CARD_REMOVE,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -67,6 +246,29 @@ export const removeUserFromCard = (id, cardId) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
removeUserFromCard.success = (cardMembership) => ({
|
||||||
|
type: ActionTypes.USER_FROM_CARD_REMOVE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
cardMembership,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
removeUserFromCard.failure = (id, cardId, error) => ({
|
||||||
|
type: ActionTypes.USER_FROM_CARD_REMOVE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
cardId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const handleUserFromCardRemove = (cardMembership) => ({
|
||||||
|
type: ActionTypes.USER_FROM_CARD_REMOVE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
cardMembership,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const addUserToBoardFilter = (id, boardId) => ({
|
export const addUserToBoardFilter = (id, boardId) => ({
|
||||||
type: ActionTypes.USER_TO_BOARD_FILTER_ADD,
|
type: ActionTypes.USER_TO_BOARD_FILTER_ADD,
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -82,202 +284,3 @@ export const removeUserFromBoardFilter = (id, boardId) => ({
|
||||||
boardId,
|
boardId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Events */
|
|
||||||
|
|
||||||
export const createUserRequested = (data) => ({
|
|
||||||
type: ActionTypes.USER_CREATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createUserSucceeded = (user) => ({
|
|
||||||
type: ActionTypes.USER_CREATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createUserFailed = (error) => ({
|
|
||||||
type: ActionTypes.USER_CREATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const createUserReceived = (user) => ({
|
|
||||||
type: ActionTypes.USER_CREATE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchCurrentUserRequested = () => ({
|
|
||||||
type: ActionTypes.CURRENT_USER_FETCH_REQUESTED,
|
|
||||||
payload: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchCurrentUserSucceeded = (user) => ({
|
|
||||||
type: ActionTypes.CURRENT_USER_FETCH_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchCurrentUserFailed = (error) => ({
|
|
||||||
type: ActionTypes.CURRENT_USER_FETCH_FAILED,
|
|
||||||
payload: {
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserRequested = (id, data) => ({
|
|
||||||
type: ActionTypes.USER_UPDATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserSucceeded = (user) => ({
|
|
||||||
type: ActionTypes.USER_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.USER_UPDATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserReceived = (user) => ({
|
|
||||||
type: ActionTypes.USER_UPDATE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserEmailRequested = (id, data) => ({
|
|
||||||
type: ActionTypes.USER_EMAIL_UPDATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserEmailSucceeded = (user) => ({
|
|
||||||
type: ActionTypes.USER_EMAIL_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserEmailFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.USER_EMAIL_UPDATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserPasswordRequested = (id, data) => ({
|
|
||||||
type: ActionTypes.USER_PASSWORD_UPDATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserPasswordSucceeded = (user) => ({
|
|
||||||
type: ActionTypes.USER_PASSWORD_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserPasswordFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.USER_PASSWORD_UPDATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserUsernameRequested = (id, data) => ({
|
|
||||||
type: ActionTypes.USER_USERNAME_UPDATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserUsernameSucceeded = (user) => ({
|
|
||||||
type: ActionTypes.USER_USERNAME_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserUsernameFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.USER_USERNAME_UPDATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserAvatarRequested = (id) => ({
|
|
||||||
type: ActionTypes.USER_AVATAR_UPDATE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserAvatarSucceeded = (user) => ({
|
|
||||||
type: ActionTypes.USER_AVATAR_UPDATE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateUserAvatarFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.USER_AVATAR_UPDATE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteUserRequested = (id) => ({
|
|
||||||
type: ActionTypes.USER_DELETE_REQUESTED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteUserSucceeded = (user) => ({
|
|
||||||
type: ActionTypes.USER_DELETE_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteUserFailed = (id, error) => ({
|
|
||||||
type: ActionTypes.USER_DELETE_FAILED,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteUserReceived = (user) => ({
|
|
||||||
type: ActionTypes.USER_DELETE_RECEIVED,
|
|
||||||
payload: {
|
|
||||||
user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
import ActionTypes from '../constants/ActionTypes';
|
|
||||||
|
|
||||||
/* Events */
|
|
||||||
|
|
||||||
export const fetchUsersRequested = () => ({
|
|
||||||
type: ActionTypes.USERS_FETCH_REQUESTED,
|
|
||||||
payload: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchUsersSucceeded = (users) => ({
|
|
||||||
type: ActionTypes.USERS_FETCH_SUCCEEDED,
|
|
||||||
payload: {
|
|
||||||
users,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchUsersFailed = (error) => ({
|
|
||||||
type: ActionTypes.USERS_FETCH_FAILED,
|
|
||||||
payload: {
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
14
client/src/api/board-memberships.js
Normal file
14
client/src/api/board-memberships.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import socket from './socket';
|
||||||
|
|
||||||
|
/* Actions */
|
||||||
|
|
||||||
|
const createBoardMembership = (boardId, data, headers) =>
|
||||||
|
socket.post(`/boards/${boardId}/memberships`, data, headers);
|
||||||
|
|
||||||
|
const deleteBoardMembership = (id, headers) =>
|
||||||
|
socket.delete(`/board-memberships/${id}`, undefined, headers);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createBoardMembership,
|
||||||
|
deleteBoardMembership,
|
||||||
|
};
|
|
@ -49,10 +49,6 @@ const createCard = (boardId, data, headers) =>
|
||||||
socket.post(`/boards/${boardId}/cards`, transformCardData(data), headers).then((body) => ({
|
socket.post(`/boards/${boardId}/cards`, transformCardData(data), headers).then((body) => ({
|
||||||
...body,
|
...body,
|
||||||
item: transformCard(body.item),
|
item: transformCard(body.item),
|
||||||
included: {
|
|
||||||
...body.included,
|
|
||||||
attachments: body.included.attachments.map(transformAttachment),
|
|
||||||
},
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const getCard = (id, headers) =>
|
const getCard = (id, headers) =>
|
||||||
|
@ -79,10 +75,6 @@ const makeHandleCardCreate = (next) => (body) => {
|
||||||
next({
|
next({
|
||||||
...body,
|
...body,
|
||||||
item: transformCard(body.item),
|
item: transformCard(body.item),
|
||||||
included: {
|
|
||||||
...body.included,
|
|
||||||
attachments: body.included.attachments.map(transformAttachment),
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,9 @@ import socket from './socket';
|
||||||
import accessTokens from './access-tokens';
|
import accessTokens from './access-tokens';
|
||||||
import users from './users';
|
import users from './users';
|
||||||
import projects from './projects';
|
import projects from './projects';
|
||||||
import projectMemberships from './project-memberships';
|
import projectManagers from './project-managers';
|
||||||
import boards from './boards';
|
import boards from './boards';
|
||||||
|
import boardMemberships from './board-memberships';
|
||||||
import labels from './labels';
|
import labels from './labels';
|
||||||
import lists from './lists';
|
import lists from './lists';
|
||||||
import cards from './cards';
|
import cards from './cards';
|
||||||
|
@ -22,8 +23,9 @@ export default {
|
||||||
...accessTokens,
|
...accessTokens,
|
||||||
...users,
|
...users,
|
||||||
...projects,
|
...projects,
|
||||||
...projectMemberships,
|
...projectManagers,
|
||||||
...boards,
|
...boards,
|
||||||
|
...boardMemberships,
|
||||||
...labels,
|
...labels,
|
||||||
...lists,
|
...lists,
|
||||||
...cards,
|
...cards,
|
||||||
|
|
|
@ -14,24 +14,21 @@ const getNotifications = (headers) =>
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const updateNotifications = (ids, data, headers) =>
|
const getNotification = (id, headers) =>
|
||||||
socket.patch(`/notifications/${ids.join(',')}`, data, headers);
|
socket.get(`/notifications/${id}`, undefined, headers).then((body) => ({
|
||||||
|
|
||||||
/* Event handlers */
|
|
||||||
|
|
||||||
const makeHandleNotificationCreate = (next) => (body) => {
|
|
||||||
next({
|
|
||||||
...body,
|
...body,
|
||||||
included: {
|
included: {
|
||||||
...body.included,
|
...body.included,
|
||||||
cards: body.included.cards.map(transformCard),
|
cards: body.included.cards.map(transformCard),
|
||||||
actions: body.included.actions.map(transformAction),
|
actions: body.included.actions.map(transformAction),
|
||||||
},
|
},
|
||||||
});
|
}));
|
||||||
};
|
|
||||||
|
const updateNotifications = (ids, data, headers) =>
|
||||||
|
socket.patch(`/notifications/${ids.join(',')}`, data, headers);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getNotifications,
|
getNotifications,
|
||||||
|
getNotification,
|
||||||
updateNotifications,
|
updateNotifications,
|
||||||
makeHandleNotificationCreate,
|
|
||||||
};
|
};
|
||||||
|
|
14
client/src/api/project-managers.js
Executable file
14
client/src/api/project-managers.js
Executable file
|
@ -0,0 +1,14 @@
|
||||||
|
import socket from './socket';
|
||||||
|
|
||||||
|
/* Actions */
|
||||||
|
|
||||||
|
const createProjectManager = (projectId, data, headers) =>
|
||||||
|
socket.post(`/projects/${projectId}/managers`, data, headers);
|
||||||
|
|
||||||
|
const deleteProjectManager = (id, headers) =>
|
||||||
|
socket.delete(`/project-managers/${id}`, undefined, headers);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createProjectManager,
|
||||||
|
deleteProjectManager,
|
||||||
|
};
|
|
@ -1,14 +0,0 @@
|
||||||
import socket from './socket';
|
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
const createProjectMembership = (projectId, data, headers) =>
|
|
||||||
socket.post(`/projects/${projectId}/memberships`, data, headers);
|
|
||||||
|
|
||||||
const deleteProjectMembership = (id, headers) =>
|
|
||||||
socket.delete(`/project-memberships/${id}`, undefined, headers);
|
|
||||||
|
|
||||||
export default {
|
|
||||||
createProjectMembership,
|
|
||||||
deleteProjectMembership,
|
|
||||||
};
|
|
|
@ -7,6 +7,8 @@ const getProjects = (headers) => socket.get('/projects', undefined, headers);
|
||||||
|
|
||||||
const createProject = (data, headers) => socket.post('/projects', data, headers);
|
const createProject = (data, headers) => socket.post('/projects', data, headers);
|
||||||
|
|
||||||
|
const getProject = (id, headers) => socket.get(`/projects/${id}`, undefined, headers);
|
||||||
|
|
||||||
const updateProject = (id, data, headers) => socket.patch(`/projects/${id}`, data, headers);
|
const updateProject = (id, data, headers) => socket.patch(`/projects/${id}`, data, headers);
|
||||||
|
|
||||||
const updateProjectBackgroundImage = (id, data, headers) =>
|
const updateProjectBackgroundImage = (id, data, headers) =>
|
||||||
|
@ -17,6 +19,7 @@ const deleteProject = (id, headers) => socket.delete(`/projects/${id}`, undefine
|
||||||
export default {
|
export default {
|
||||||
getProjects,
|
getProjects,
|
||||||
createProject,
|
createProject,
|
||||||
|
getProject,
|
||||||
updateProject,
|
updateProject,
|
||||||
updateProjectBackgroundImage,
|
updateProjectBackgroundImage,
|
||||||
deleteProject,
|
deleteProject,
|
||||||
|
|
|
@ -7,6 +7,8 @@ const getUsers = (headers) => socket.get('/users', undefined, headers);
|
||||||
|
|
||||||
const createUser = (data, headers) => socket.post('/users', data, headers);
|
const createUser = (data, headers) => socket.post('/users', data, headers);
|
||||||
|
|
||||||
|
const getUser = (id, headers) => socket.get(`/users/${id}`, undefined, headers);
|
||||||
|
|
||||||
const getCurrentUser = (headers) => socket.get('/users/me', undefined, headers);
|
const getCurrentUser = (headers) => socket.get('/users/me', undefined, headers);
|
||||||
|
|
||||||
const updateUser = (id, data, headers) => socket.patch(`/users/${id}`, data, headers);
|
const updateUser = (id, data, headers) => socket.patch(`/users/${id}`, data, headers);
|
||||||
|
@ -26,6 +28,7 @@ const deleteUser = (id, headers) => socket.delete(`/users/${id}`, undefined, hea
|
||||||
export default {
|
export default {
|
||||||
getUsers,
|
getUsers,
|
||||||
createUser,
|
createUser,
|
||||||
|
getUser,
|
||||||
getCurrentUser,
|
getCurrentUser,
|
||||||
updateUser,
|
updateUser,
|
||||||
updateUserEmail,
|
updateUserEmail,
|
||||||
|
|
78
client/src/components/BoardActions/BoardActions.jsx
Normal file
78
client/src/components/BoardActions/BoardActions.jsx
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Filters from './Filters';
|
||||||
|
import Memberships from '../Memberships';
|
||||||
|
|
||||||
|
import styles from './BoardActions.module.scss';
|
||||||
|
|
||||||
|
const BoardActions = React.memo(
|
||||||
|
({
|
||||||
|
memberships,
|
||||||
|
labels,
|
||||||
|
filterUsers,
|
||||||
|
filterLabels,
|
||||||
|
allUsers,
|
||||||
|
canEditMemberships,
|
||||||
|
onMembershipCreate,
|
||||||
|
onMembershipDelete,
|
||||||
|
onUserToFilterAdd,
|
||||||
|
onUserFromFilterRemove,
|
||||||
|
onLabelToFilterAdd,
|
||||||
|
onLabelFromFilterRemove,
|
||||||
|
onLabelCreate,
|
||||||
|
onLabelUpdate,
|
||||||
|
onLabelDelete,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className={styles.actions}>
|
||||||
|
<div className={styles.action}>
|
||||||
|
<Memberships
|
||||||
|
items={memberships}
|
||||||
|
allUsers={allUsers}
|
||||||
|
canEdit={canEditMemberships}
|
||||||
|
onCreate={onMembershipCreate}
|
||||||
|
onDelete={onMembershipDelete}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={styles.action}>
|
||||||
|
<Filters
|
||||||
|
users={filterUsers}
|
||||||
|
labels={filterLabels}
|
||||||
|
allBoardMemberships={memberships}
|
||||||
|
allLabels={labels}
|
||||||
|
onUserAdd={onUserToFilterAdd}
|
||||||
|
onUserRemove={onUserFromFilterRemove}
|
||||||
|
onLabelAdd={onLabelToFilterAdd}
|
||||||
|
onLabelRemove={onLabelFromFilterRemove}
|
||||||
|
onLabelCreate={onLabelCreate}
|
||||||
|
onLabelUpdate={onLabelUpdate}
|
||||||
|
onLabelDelete={onLabelDelete}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
BoardActions.propTypes = {
|
||||||
|
/* eslint-disable react/forbid-prop-types */
|
||||||
|
memberships: PropTypes.array.isRequired,
|
||||||
|
labels: PropTypes.array.isRequired,
|
||||||
|
filterUsers: PropTypes.array.isRequired,
|
||||||
|
filterLabels: PropTypes.array.isRequired,
|
||||||
|
allUsers: PropTypes.array.isRequired,
|
||||||
|
/* eslint-enable react/forbid-prop-types */
|
||||||
|
canEditMemberships: PropTypes.bool.isRequired,
|
||||||
|
onMembershipCreate: PropTypes.func.isRequired,
|
||||||
|
onMembershipDelete: PropTypes.func.isRequired,
|
||||||
|
onUserToFilterAdd: PropTypes.func.isRequired,
|
||||||
|
onUserFromFilterRemove: PropTypes.func.isRequired,
|
||||||
|
onLabelToFilterAdd: PropTypes.func.isRequired,
|
||||||
|
onLabelFromFilterRemove: PropTypes.func.isRequired,
|
||||||
|
onLabelCreate: PropTypes.func.isRequired,
|
||||||
|
onLabelUpdate: PropTypes.func.isRequired,
|
||||||
|
onLabelDelete: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BoardActions;
|
11
client/src/components/BoardActions/BoardActions.module.scss
Normal file
11
client/src/components/BoardActions/BoardActions.module.scss
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
:global(#app) {
|
||||||
|
.action {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
margin: 20px 20px;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,16 +4,16 @@ import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import User from '../User';
|
import User from '../User';
|
||||||
import Label from '../Label';
|
import Label from '../Label';
|
||||||
import ProjectMembershipsPopup from '../ProjectMembershipsPopup';
|
import BoardMembershipsPopup from '../BoardMembershipsPopup';
|
||||||
import LabelsPopup from '../LabelsPopup';
|
import LabelsPopup from '../LabelsPopup';
|
||||||
|
|
||||||
import styles from './Filter.module.scss';
|
import styles from './Filters.module.scss';
|
||||||
|
|
||||||
const Filter = React.memo(
|
const Filters = React.memo(
|
||||||
({
|
({
|
||||||
users,
|
users,
|
||||||
labels,
|
labels,
|
||||||
allProjectMemberships,
|
allBoardMemberships,
|
||||||
allLabels,
|
allLabels,
|
||||||
onUserAdd,
|
onUserAdd,
|
||||||
onUserRemove,
|
onUserRemove,
|
||||||
|
@ -40,10 +40,10 @@ const Filter = React.memo(
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.filters}>
|
<>
|
||||||
<span className={styles.filter}>
|
<span className={styles.filter}>
|
||||||
<ProjectMembershipsPopup
|
<BoardMembershipsPopup
|
||||||
items={allProjectMemberships}
|
items={allBoardMemberships}
|
||||||
currentUserIds={users.map((user) => user.id)}
|
currentUserIds={users.map((user) => user.id)}
|
||||||
title={t('common.filterByMembers', {
|
title={t('common.filterByMembers', {
|
||||||
context: 'title',
|
context: 'title',
|
||||||
|
@ -55,7 +55,7 @@ const Filter = React.memo(
|
||||||
<span className={styles.filterTitle}>{`${t('common.members')}:`}</span>
|
<span className={styles.filterTitle}>{`${t('common.members')}:`}</span>
|
||||||
{users.length === 0 && <span className={styles.filterLabel}>{t('common.all')}</span>}
|
{users.length === 0 && <span className={styles.filterLabel}>{t('common.all')}</span>}
|
||||||
</button>
|
</button>
|
||||||
</ProjectMembershipsPopup>
|
</BoardMembershipsPopup>
|
||||||
{users.map((user) => (
|
{users.map((user) => (
|
||||||
<span key={user.id} className={styles.filterItem}>
|
<span key={user.id} className={styles.filterItem}>
|
||||||
<User
|
<User
|
||||||
|
@ -96,16 +96,16 @@ const Filter = React.memo(
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Filter.propTypes = {
|
Filters.propTypes = {
|
||||||
/* eslint-disable react/forbid-prop-types */
|
/* eslint-disable react/forbid-prop-types */
|
||||||
users: PropTypes.array.isRequired,
|
users: PropTypes.array.isRequired,
|
||||||
labels: PropTypes.array.isRequired,
|
labels: PropTypes.array.isRequired,
|
||||||
allProjectMemberships: PropTypes.array.isRequired,
|
allBoardMemberships: PropTypes.array.isRequired,
|
||||||
allLabels: PropTypes.array.isRequired,
|
allLabels: PropTypes.array.isRequired,
|
||||||
/* eslint-enable react/forbid-prop-types */
|
/* eslint-enable react/forbid-prop-types */
|
||||||
onUserAdd: PropTypes.func.isRequired,
|
onUserAdd: PropTypes.func.isRequired,
|
||||||
|
@ -117,4 +117,4 @@ Filter.propTypes = {
|
||||||
onLabelDelete: PropTypes.func.isRequired,
|
onLabelDelete: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Filter;
|
export default Filters;
|
|
@ -1,8 +1,6 @@
|
||||||
:global(#app) {
|
:global(#app) {
|
||||||
.filter {
|
.filter {
|
||||||
display: inline-block;
|
margin-right: 10px;
|
||||||
line-height: 0;
|
|
||||||
margin-right: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.filterButton {
|
.filterButton {
|
||||||
|
@ -45,9 +43,4 @@
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
padding: 2px 12px;
|
padding: 2px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filters {
|
|
||||||
line-height: 0;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
}
|
}
|
3
client/src/components/BoardActions/index.js
Normal file
3
client/src/components/BoardActions/index.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import BoardActions from './BoardActions';
|
||||||
|
|
||||||
|
export default BoardActions;
|
|
@ -8,7 +8,6 @@ import DroppableTypes from '../../constants/DroppableTypes';
|
||||||
import ListContainer from '../../containers/ListContainer';
|
import ListContainer from '../../containers/ListContainer';
|
||||||
import CardModalContainer from '../../containers/CardModalContainer';
|
import CardModalContainer from '../../containers/CardModalContainer';
|
||||||
import ListAdd from './ListAdd';
|
import ListAdd from './ListAdd';
|
||||||
import Filter from './Filter';
|
|
||||||
import { ReactComponent as PlusMathIcon } from '../../assets/images/plus-math-icon.svg';
|
import { ReactComponent as PlusMathIcon } from '../../assets/images/plus-math-icon.svg';
|
||||||
|
|
||||||
import styles from './BoardKanban.module.scss';
|
import styles from './BoardKanban.module.scss';
|
||||||
|
@ -16,36 +15,19 @@ import styles from './BoardKanban.module.scss';
|
||||||
const parseDndId = (dndId) => dndId.split(':')[1];
|
const parseDndId = (dndId) => dndId.split(':')[1];
|
||||||
|
|
||||||
const BoardKanban = React.memo(
|
const BoardKanban = React.memo(
|
||||||
({
|
({ listIds, isCardModalOpened, canEdit, onListCreate, onListMove, onCardMove }) => {
|
||||||
listIds,
|
|
||||||
filterUsers,
|
|
||||||
filterLabels,
|
|
||||||
allProjectMemberships,
|
|
||||||
allLabels,
|
|
||||||
isCardModalOpened,
|
|
||||||
onListCreate,
|
|
||||||
onListMove,
|
|
||||||
onCardMove,
|
|
||||||
onUserToFilterAdd,
|
|
||||||
onUserFromFilterRemove,
|
|
||||||
onLabelToFilterAdd,
|
|
||||||
onLabelFromFilterRemove,
|
|
||||||
onLabelCreate,
|
|
||||||
onLabelUpdate,
|
|
||||||
onLabelDelete,
|
|
||||||
}) => {
|
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const [isAddListOpened, setIsAddListOpened] = useState(false);
|
const [isListAddOpened, setIsListAddOpened] = useState(false);
|
||||||
|
|
||||||
const wrapper = useRef(null);
|
const wrapper = useRef(null);
|
||||||
const prevPosition = useRef(null);
|
const prevPosition = useRef(null);
|
||||||
|
|
||||||
const handleAddListClick = useCallback(() => {
|
const handleAddListClick = useCallback(() => {
|
||||||
setIsAddListOpened(true);
|
setIsListAddOpened(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleAddListClose = useCallback(() => {
|
const handleAddListClose = useCallback(() => {
|
||||||
setIsAddListOpened(false);
|
setIsListAddOpened(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleDragStart = useCallback(() => {
|
const handleDragStart = useCallback(() => {
|
||||||
|
@ -119,10 +101,10 @@ const BoardKanban = React.memo(
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isAddListOpened) {
|
if (isListAddOpened) {
|
||||||
window.scroll(document.body.scrollWidth, 0);
|
window.scroll(document.body.scrollWidth, 0);
|
||||||
}
|
}
|
||||||
}, [listIds, isAddListOpened]);
|
}, [listIds, isListAddOpened]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener('mouseup', handleWindowMouseUp);
|
window.addEventListener('mouseup', handleWindowMouseUp);
|
||||||
|
@ -138,19 +120,6 @@ const BoardKanban = React.memo(
|
||||||
<>
|
<>
|
||||||
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
|
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
|
||||||
<div ref={wrapper} className={styles.wrapper} onMouseDown={handleMouseDown}>
|
<div ref={wrapper} className={styles.wrapper} onMouseDown={handleMouseDown}>
|
||||||
<Filter
|
|
||||||
users={filterUsers}
|
|
||||||
labels={filterLabels}
|
|
||||||
allProjectMemberships={allProjectMemberships}
|
|
||||||
allLabels={allLabels}
|
|
||||||
onUserAdd={onUserToFilterAdd}
|
|
||||||
onUserRemove={onUserFromFilterRemove}
|
|
||||||
onLabelAdd={onLabelToFilterAdd}
|
|
||||||
onLabelRemove={onLabelFromFilterRemove}
|
|
||||||
onLabelCreate={onLabelCreate}
|
|
||||||
onLabelUpdate={onLabelUpdate}
|
|
||||||
onLabelDelete={onLabelDelete}
|
|
||||||
/>
|
|
||||||
<div>
|
<div>
|
||||||
<DragDropContext onDragStart={handleDragStart} onDragEnd={handleDragEnd}>
|
<DragDropContext onDragStart={handleDragStart} onDragEnd={handleDragEnd}>
|
||||||
<Droppable droppableId="board" type={DroppableTypes.LIST} direction="horizontal">
|
<Droppable droppableId="board" type={DroppableTypes.LIST} direction="horizontal">
|
||||||
|
@ -165,26 +134,26 @@ const BoardKanban = React.memo(
|
||||||
<ListContainer key={listId} id={listId} index={index} />
|
<ListContainer key={listId} id={listId} index={index} />
|
||||||
))}
|
))}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
<div data-drag-scroller className={styles.list}>
|
{canEdit && (
|
||||||
{isAddListOpened ? (
|
<div data-drag-scroller className={styles.list}>
|
||||||
<ListAdd
|
{isListAddOpened ? (
|
||||||
isOpened={isAddListOpened}
|
<ListAdd onCreate={onListCreate} onClose={handleAddListClose} />
|
||||||
onCreate={onListCreate}
|
) : (
|
||||||
onClose={handleAddListClose}
|
<button
|
||||||
/>
|
type="button"
|
||||||
) : (
|
className={styles.addListButton}
|
||||||
<button
|
onClick={handleAddListClick}
|
||||||
type="button"
|
>
|
||||||
className={styles.addListButton}
|
<PlusMathIcon className={styles.addListButtonIcon} />
|
||||||
onClick={handleAddListClick}
|
<span className={styles.addListButtonText}>
|
||||||
>
|
{listIds.length > 0
|
||||||
<PlusMathIcon className={styles.addListButtonIcon} />
|
? t('action.addAnotherList')
|
||||||
<span className={styles.addListButtonText}>
|
: t('action.addList')}
|
||||||
{listIds.length > 0 ? t('action.addAnotherList') : t('action.addList')}
|
</span>
|
||||||
</span>
|
</button>
|
||||||
</button>
|
)}
|
||||||
)}
|
</div>
|
||||||
</div>
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Droppable>
|
</Droppable>
|
||||||
|
@ -198,24 +167,12 @@ const BoardKanban = React.memo(
|
||||||
);
|
);
|
||||||
|
|
||||||
BoardKanban.propTypes = {
|
BoardKanban.propTypes = {
|
||||||
/* eslint-disable react/forbid-prop-types */
|
listIds: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
listIds: PropTypes.array.isRequired,
|
|
||||||
filterUsers: PropTypes.array.isRequired,
|
|
||||||
filterLabels: PropTypes.array.isRequired,
|
|
||||||
allProjectMemberships: PropTypes.array.isRequired,
|
|
||||||
allLabels: PropTypes.array.isRequired,
|
|
||||||
/* eslint-enable react/forbid-prop-types */
|
|
||||||
isCardModalOpened: PropTypes.bool.isRequired,
|
isCardModalOpened: PropTypes.bool.isRequired,
|
||||||
|
canEdit: PropTypes.bool.isRequired,
|
||||||
onListCreate: PropTypes.func.isRequired,
|
onListCreate: PropTypes.func.isRequired,
|
||||||
onListMove: PropTypes.func.isRequired,
|
onListMove: PropTypes.func.isRequired,
|
||||||
onCardMove: PropTypes.func.isRequired,
|
onCardMove: PropTypes.func.isRequired,
|
||||||
onUserToFilterAdd: PropTypes.func.isRequired,
|
|
||||||
onUserFromFilterRemove: PropTypes.func.isRequired,
|
|
||||||
onLabelToFilterAdd: PropTypes.func.isRequired,
|
|
||||||
onLabelFromFilterRemove: PropTypes.func.isRequired,
|
|
||||||
onLabelCreate: PropTypes.func.isRequired,
|
|
||||||
onLabelUpdate: PropTypes.func.isRequired,
|
|
||||||
onLabelDelete: PropTypes.func.isRequired,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default BoardKanban;
|
export default BoardKanban;
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.list {
|
.list {
|
||||||
margin: 0 20px 0 4px;
|
margin-right: 20px;
|
||||||
width: 272px;
|
width: 272px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,16 @@
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panelItem {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
margin: 0 20px;
|
margin: 0 20px;
|
||||||
}
|
}
|
||||||
|
|
5
client/src/components/BoardMembershipsPopup.jsx
Normal file
5
client/src/components/BoardMembershipsPopup.jsx
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { withPopup } from '../lib/popup';
|
||||||
|
|
||||||
|
import BoardMembershipsStep from './BoardMembershipsStep';
|
||||||
|
|
||||||
|
export default withPopup(BoardMembershipsStep);
|
|
@ -6,9 +6,9 @@ import { Popup } from '../../lib/custom-ui';
|
||||||
|
|
||||||
import Item from './Item';
|
import Item from './Item';
|
||||||
|
|
||||||
import styles from './ProjectMembershipsStep.module.scss';
|
import styles from './BoardMembershipsStep.module.scss';
|
||||||
|
|
||||||
const ProjectMembershipsStep = React.memo(
|
const BoardMembershipsStep = React.memo(
|
||||||
({ items, currentUserIds, title, onUserSelect, onUserDeselect, onBack }) => {
|
({ items, currentUserIds, title, onUserSelect, onUserDeselect, onBack }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ const ProjectMembershipsStep = React.memo(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
ProjectMembershipsStep.propTypes = {
|
BoardMembershipsStep.propTypes = {
|
||||||
/* eslint-disable react/forbid-prop-types */
|
/* eslint-disable react/forbid-prop-types */
|
||||||
items: PropTypes.array.isRequired,
|
items: PropTypes.array.isRequired,
|
||||||
currentUserIds: PropTypes.array.isRequired,
|
currentUserIds: PropTypes.array.isRequired,
|
||||||
|
@ -59,9 +59,9 @@ ProjectMembershipsStep.propTypes = {
|
||||||
onBack: PropTypes.func,
|
onBack: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
ProjectMembershipsStep.defaultProps = {
|
BoardMembershipsStep.defaultProps = {
|
||||||
title: 'common.members',
|
title: 'common.members',
|
||||||
onBack: undefined,
|
onBack: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ProjectMembershipsStep;
|
export default BoardMembershipsStep;
|
3
client/src/components/BoardMembershipsStep/index.js
Executable file
3
client/src/components/BoardMembershipsStep/index.js
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
import BoardMembershipsStep from './BoardMembershipsStep';
|
||||||
|
|
||||||
|
export default BoardMembershipsStep;
|
|
@ -14,145 +14,117 @@ import EditPopup from './EditPopup';
|
||||||
|
|
||||||
import styles from './Boards.module.scss';
|
import styles from './Boards.module.scss';
|
||||||
|
|
||||||
const Boards = React.memo(
|
const Boards = React.memo(({ items, currentId, canEdit, onCreate, onUpdate, onMove, onDelete }) => {
|
||||||
({ items, currentId, isEditable, onCreate, onUpdate, onMove, onDelete }) => {
|
const tabsWrapper = useRef(null);
|
||||||
const tabsWrapper = useRef(null);
|
|
||||||
|
|
||||||
const handleWheel = useCallback(({ deltaY }) => {
|
const handleWheel = useCallback(({ deltaY }) => {
|
||||||
tabsWrapper.current.scrollBy({
|
tabsWrapper.current.scrollBy({
|
||||||
left: deltaY,
|
left: deltaY,
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleDragStart = useCallback(() => {
|
const handleDragStart = useCallback(() => {
|
||||||
closePopup();
|
closePopup();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleDragEnd = useCallback(
|
const handleDragEnd = useCallback(
|
||||||
({ draggableId, source, destination }) => {
|
({ draggableId, source, destination }) => {
|
||||||
if (!destination || source.index === destination.index) {
|
if (!destination || source.index === destination.index) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMove(draggableId, destination.index);
|
onMove(draggableId, destination.index);
|
||||||
},
|
},
|
||||||
[onMove],
|
[onMove],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleUpdate = useCallback(
|
const handleUpdate = useCallback(
|
||||||
(id, data) => {
|
(id, data) => {
|
||||||
onUpdate(id, data);
|
onUpdate(id, data);
|
||||||
},
|
},
|
||||||
[onUpdate],
|
[onUpdate],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDelete = useCallback(
|
const handleDelete = useCallback(
|
||||||
(id) => {
|
(id) => {
|
||||||
onDelete(id);
|
onDelete(id);
|
||||||
},
|
},
|
||||||
[onDelete],
|
[onDelete],
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderItems = useCallback(
|
const itemsNode = items.map((item, index) => (
|
||||||
(safeItems) =>
|
<Draggable
|
||||||
safeItems.map((item) => (
|
key={item.id}
|
||||||
<div key={item.id} className={styles.tabWrapper}>
|
draggableId={item.id}
|
||||||
<div className={classNames(styles.tab, item.id === currentId && styles.tabActive)}>
|
index={index}
|
||||||
{item.isPersisted ? (
|
isDragDisabled={!item.isPersisted || !canEdit}
|
||||||
|
>
|
||||||
|
{({ innerRef, draggableProps, dragHandleProps }) => (
|
||||||
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
|
<div {...draggableProps} ref={innerRef} className={styles.tabWrapper}>
|
||||||
|
<div className={classNames(styles.tab, item.id === currentId && styles.tabActive)}>
|
||||||
|
{item.isPersisted ? (
|
||||||
|
<>
|
||||||
<Link
|
<Link
|
||||||
|
{...dragHandleProps} // eslint-disable-line react/jsx-props-no-spreading
|
||||||
to={Paths.BOARDS.replace(':id', item.id)}
|
to={Paths.BOARDS.replace(':id', item.id)}
|
||||||
title={item.name}
|
title={item.name}
|
||||||
className={styles.link}
|
className={styles.link}
|
||||||
>
|
>
|
||||||
{item.name}
|
{item.name}
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
{canEdit && (
|
||||||
<span className={styles.link}>{item.name}</span>
|
<EditPopup
|
||||||
)}
|
defaultData={pick(item, 'name')}
|
||||||
</div>
|
onUpdate={(data) => handleUpdate(item.id, data)}
|
||||||
</div>
|
onDelete={() => handleDelete(item.id)}
|
||||||
)),
|
>
|
||||||
[currentId],
|
<Button className={classNames(styles.editButton, styles.target)}>
|
||||||
);
|
<Icon fitted name="pencil" size="small" />
|
||||||
|
</Button>
|
||||||
const renderEditableItems = useCallback(
|
</EditPopup>
|
||||||
(safeItems) =>
|
)}
|
||||||
safeItems.map((item, index) => (
|
</>
|
||||||
<Draggable
|
) : (
|
||||||
key={item.id}
|
|
||||||
draggableId={item.id}
|
|
||||||
index={index}
|
|
||||||
isDragDisabled={!item.isPersisted}
|
|
||||||
>
|
|
||||||
{({ innerRef, draggableProps, dragHandleProps }) => (
|
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
<div {...draggableProps} ref={innerRef} className={styles.tabWrapper}>
|
<span {...dragHandleProps} className={styles.link}>
|
||||||
<div className={classNames(styles.tab, item.id === currentId && styles.tabActive)}>
|
{item.name}
|
||||||
{item.isPersisted ? (
|
</span>
|
||||||
<Link
|
)}
|
||||||
{...dragHandleProps} // eslint-disable-line react/jsx-props-no-spreading
|
</div>
|
||||||
to={Paths.BOARDS.replace(':id', item.id)}
|
</div>
|
||||||
title={item.name}
|
)}
|
||||||
className={styles.link}
|
</Draggable>
|
||||||
>
|
));
|
||||||
{item.name}
|
|
||||||
</Link>
|
return (
|
||||||
) : (
|
<div className={styles.wrapper} onWheel={handleWheel}>
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
<div ref={tabsWrapper} className={styles.tabsWrapper}>
|
||||||
<span {...dragHandleProps} className={styles.link}>
|
<DragDropContext onDragStart={handleDragStart} onDragEnd={handleDragEnd}>
|
||||||
{item.name}
|
<Droppable droppableId="boards" type={DroppableTypes.BOARD} direction="horizontal">
|
||||||
</span>
|
{({ innerRef, droppableProps, placeholder }) => (
|
||||||
)}
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
{item.isPersisted && (
|
<div {...droppableProps} ref={innerRef} className={styles.tabs}>
|
||||||
<EditPopup
|
{itemsNode}
|
||||||
defaultData={pick(item, 'name')}
|
{placeholder}
|
||||||
onUpdate={(data) => handleUpdate(item.id, data)}
|
{canEdit && (
|
||||||
onDelete={() => handleDelete(item.id)}
|
<AddPopup onCreate={onCreate}>
|
||||||
>
|
<Button icon="plus" className={styles.addButton} />
|
||||||
<Button className={classNames(styles.editButton, styles.target)}>
|
</AddPopup>
|
||||||
<Icon fitted name="pencil" size="small" />
|
)}
|
||||||
</Button>
|
|
||||||
</EditPopup>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Draggable>
|
</Droppable>
|
||||||
)),
|
</DragDropContext>
|
||||||
[currentId, handleUpdate, handleDelete],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.wrapper} onWheel={handleWheel}>
|
|
||||||
<div ref={tabsWrapper} className={styles.tabsWrapper}>
|
|
||||||
{isEditable ? (
|
|
||||||
<DragDropContext onDragStart={handleDragStart} onDragEnd={handleDragEnd}>
|
|
||||||
<Droppable droppableId="boards" type={DroppableTypes.BOARD} direction="horizontal">
|
|
||||||
{({ innerRef, droppableProps, placeholder }) => (
|
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
||||||
<div {...droppableProps} ref={innerRef} className={styles.tabs}>
|
|
||||||
{renderEditableItems(items)}
|
|
||||||
{placeholder}
|
|
||||||
<AddPopup onCreate={onCreate}>
|
|
||||||
<Button icon="plus" className={styles.addButton} />
|
|
||||||
</AddPopup>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Droppable>
|
|
||||||
</DragDropContext>
|
|
||||||
) : (
|
|
||||||
<div className={styles.tabs}>{renderItems(items)}</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
</div>
|
||||||
},
|
);
|
||||||
);
|
});
|
||||||
|
|
||||||
Boards.propTypes = {
|
Boards.propTypes = {
|
||||||
items: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
items: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
currentId: PropTypes.string,
|
currentId: PropTypes.string,
|
||||||
isEditable: PropTypes.bool.isRequired,
|
canEdit: PropTypes.bool.isRequired,
|
||||||
onCreate: PropTypes.func.isRequired,
|
onCreate: PropTypes.func.isRequired,
|
||||||
onUpdate: PropTypes.func.isRequired,
|
onUpdate: PropTypes.func.isRequired,
|
||||||
onMove: PropTypes.func.isRequired,
|
onMove: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
.link {
|
.link {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
display: block;
|
display: block;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
padding: 10px 34px 6px 14px;
|
padding: 10px 34px 6px 14px;
|
||||||
|
@ -99,15 +100,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
border-bottom: 2px solid rgba(0, 0, 0, 0.24);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.24);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { withPopup } from '../../lib/popup';
|
||||||
import { Popup } from '../../lib/custom-ui';
|
import { Popup } from '../../lib/custom-ui';
|
||||||
|
|
||||||
import { useSteps } from '../../hooks';
|
import { useSteps } from '../../hooks';
|
||||||
import ProjectMembershipsStep from '../ProjectMembershipsStep';
|
import BoardMembershipsStep from '../BoardMembershipsStep';
|
||||||
import LabelsStep from '../LabelsStep';
|
import LabelsStep from '../LabelsStep';
|
||||||
import DueDateEditStep from '../DueDateEditStep';
|
import DueDateEditStep from '../DueDateEditStep';
|
||||||
import TimerEditStep from '../TimerEditStep';
|
import TimerEditStep from '../TimerEditStep';
|
||||||
|
@ -29,7 +29,7 @@ const ActionsStep = React.memo(
|
||||||
({
|
({
|
||||||
card,
|
card,
|
||||||
projectsToLists,
|
projectsToLists,
|
||||||
projectMemberships,
|
boardMemberships,
|
||||||
currentUserIds,
|
currentUserIds,
|
||||||
labels,
|
labels,
|
||||||
currentLabelIds,
|
currentLabelIds,
|
||||||
|
@ -102,8 +102,8 @@ const ActionsStep = React.memo(
|
||||||
switch (step.type) {
|
switch (step.type) {
|
||||||
case StepTypes.USERS:
|
case StepTypes.USERS:
|
||||||
return (
|
return (
|
||||||
<ProjectMembershipsStep
|
<BoardMembershipsStep
|
||||||
items={projectMemberships}
|
items={boardMemberships}
|
||||||
currentUserIds={currentUserIds}
|
currentUserIds={currentUserIds}
|
||||||
onUserSelect={onUserAdd}
|
onUserSelect={onUserAdd}
|
||||||
onUserDeselect={onUserRemove}
|
onUserDeselect={onUserRemove}
|
||||||
|
@ -224,7 +224,7 @@ ActionsStep.propTypes = {
|
||||||
/* eslint-disable react/forbid-prop-types */
|
/* eslint-disable react/forbid-prop-types */
|
||||||
card: PropTypes.object.isRequired,
|
card: PropTypes.object.isRequired,
|
||||||
projectsToLists: PropTypes.array.isRequired,
|
projectsToLists: PropTypes.array.isRequired,
|
||||||
projectMemberships: PropTypes.array.isRequired,
|
boardMemberships: PropTypes.array.isRequired,
|
||||||
currentUserIds: PropTypes.array.isRequired,
|
currentUserIds: PropTypes.array.isRequired,
|
||||||
labels: PropTypes.array.isRequired,
|
labels: PropTypes.array.isRequired,
|
||||||
currentLabelIds: PropTypes.array.isRequired,
|
currentLabelIds: PropTypes.array.isRequired,
|
||||||
|
|
|
@ -33,8 +33,9 @@ const Card = React.memo(
|
||||||
labels,
|
labels,
|
||||||
tasks,
|
tasks,
|
||||||
allProjectsToLists,
|
allProjectsToLists,
|
||||||
allProjectMemberships,
|
allBoardMemberships,
|
||||||
allLabels,
|
allLabels,
|
||||||
|
canEdit,
|
||||||
onUpdate,
|
onUpdate,
|
||||||
onMove,
|
onMove,
|
||||||
onTransfer,
|
onTransfer,
|
||||||
|
@ -129,7 +130,7 @@ const Card = React.memo(
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Draggable draggableId={`card:${id}`} index={index} isDragDisabled={!isPersisted}>
|
<Draggable draggableId={`card:${id}`} index={index} isDragDisabled={!isPersisted || !canEdit}>
|
||||||
{({ innerRef, draggableProps, dragHandleProps }) => (
|
{({ innerRef, draggableProps, dragHandleProps }) => (
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
<div {...draggableProps} {...dragHandleProps} ref={innerRef} className={styles.wrapper}>
|
<div {...draggableProps} {...dragHandleProps} ref={innerRef} className={styles.wrapper}>
|
||||||
|
@ -144,40 +145,42 @@ const Card = React.memo(
|
||||||
>
|
>
|
||||||
{contentNode}
|
{contentNode}
|
||||||
</Link>
|
</Link>
|
||||||
<ActionsPopup
|
{canEdit && (
|
||||||
card={{
|
<ActionsPopup
|
||||||
id,
|
card={{
|
||||||
name,
|
id,
|
||||||
dueDate,
|
name,
|
||||||
timer,
|
dueDate,
|
||||||
boardId,
|
timer,
|
||||||
listId,
|
boardId,
|
||||||
projectId,
|
listId,
|
||||||
isPersisted,
|
projectId,
|
||||||
}}
|
isPersisted,
|
||||||
projectsToLists={allProjectsToLists}
|
}}
|
||||||
projectMemberships={allProjectMemberships}
|
projectsToLists={allProjectsToLists}
|
||||||
currentUserIds={users.map((user) => user.id)}
|
boardMemberships={allBoardMemberships}
|
||||||
labels={allLabels}
|
currentUserIds={users.map((user) => user.id)}
|
||||||
currentLabelIds={labels.map((label) => label.id)}
|
labels={allLabels}
|
||||||
onNameEdit={handleNameEdit}
|
currentLabelIds={labels.map((label) => label.id)}
|
||||||
onUpdate={onUpdate}
|
onNameEdit={handleNameEdit}
|
||||||
onMove={onMove}
|
onUpdate={onUpdate}
|
||||||
onTransfer={onTransfer}
|
onMove={onMove}
|
||||||
onDelete={onDelete}
|
onTransfer={onTransfer}
|
||||||
onUserAdd={onUserAdd}
|
onDelete={onDelete}
|
||||||
onUserRemove={onUserRemove}
|
onUserAdd={onUserAdd}
|
||||||
onBoardFetch={onBoardFetch}
|
onUserRemove={onUserRemove}
|
||||||
onLabelAdd={onLabelAdd}
|
onBoardFetch={onBoardFetch}
|
||||||
onLabelRemove={onLabelRemove}
|
onLabelAdd={onLabelAdd}
|
||||||
onLabelCreate={onLabelCreate}
|
onLabelRemove={onLabelRemove}
|
||||||
onLabelUpdate={onLabelUpdate}
|
onLabelCreate={onLabelCreate}
|
||||||
onLabelDelete={onLabelDelete}
|
onLabelUpdate={onLabelUpdate}
|
||||||
>
|
onLabelDelete={onLabelDelete}
|
||||||
<Button className={classNames(styles.actionsButton, styles.target)}>
|
>
|
||||||
<Icon fitted name="pencil" size="small" />
|
<Button className={classNames(styles.actionsButton, styles.target)}>
|
||||||
</Button>
|
<Icon fitted name="pencil" size="small" />
|
||||||
</ActionsPopup>
|
</Button>
|
||||||
|
</ActionsPopup>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<span className={styles.content}>{contentNode}</span>
|
<span className={styles.content}>{contentNode}</span>
|
||||||
|
@ -208,9 +211,10 @@ Card.propTypes = {
|
||||||
labels: PropTypes.array.isRequired,
|
labels: PropTypes.array.isRequired,
|
||||||
tasks: PropTypes.array.isRequired,
|
tasks: PropTypes.array.isRequired,
|
||||||
allProjectsToLists: PropTypes.array.isRequired,
|
allProjectsToLists: PropTypes.array.isRequired,
|
||||||
allProjectMemberships: PropTypes.array.isRequired,
|
allBoardMemberships: PropTypes.array.isRequired,
|
||||||
allLabels: PropTypes.array.isRequired,
|
allLabels: PropTypes.array.isRequired,
|
||||||
/* eslint-enable react/forbid-prop-types */
|
/* eslint-enable react/forbid-prop-types */
|
||||||
|
canEdit: PropTypes.bool.isRequired,
|
||||||
onUpdate: PropTypes.func.isRequired,
|
onUpdate: PropTypes.func.isRequired,
|
||||||
onMove: PropTypes.func.isRequired,
|
onMove: PropTypes.func.isRequired,
|
||||||
onTransfer: PropTypes.func.isRequired,
|
onTransfer: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -54,7 +54,6 @@
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
box-shadow: 0 1px 0 #ccc;
|
box-shadow: 0 1px 0 #ccc;
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #f5f6f7;
|
background: #f5f6f7;
|
||||||
|
@ -67,7 +66,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
cursor: grab;
|
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
.button {
|
.button {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
margin: 0 -8px;
|
margin: 0 -8px;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
@ -12,7 +11,6 @@
|
||||||
|
|
||||||
.count {
|
.count {
|
||||||
color: #888;
|
color: #888;
|
||||||
cursor: pointer;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 12px;
|
line-height: 12px;
|
||||||
|
@ -77,7 +75,6 @@
|
||||||
|
|
||||||
.tasks {
|
.tasks {
|
||||||
color: #333;
|
color: #333;
|
||||||
cursor: grab;
|
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: -2px 0 0;
|
margin: -2px 0 0;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
|
|
@ -14,7 +14,8 @@ const Actions = React.memo(
|
||||||
items,
|
items,
|
||||||
isFetching,
|
isFetching,
|
||||||
isAllFetched,
|
isAllFetched,
|
||||||
isEditable,
|
canEdit,
|
||||||
|
canEditAllComments,
|
||||||
onFetch,
|
onFetch,
|
||||||
onCommentCreate,
|
onCommentCreate,
|
||||||
onCommentUpdate,
|
onCommentUpdate,
|
||||||
|
@ -38,13 +39,15 @@ const Actions = React.memo(
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={styles.contentModule}>
|
{canEdit && (
|
||||||
<div className={styles.moduleWrapper}>
|
<div className={styles.contentModule}>
|
||||||
<Icon name="comment outline" className={styles.moduleIcon} />
|
<div className={styles.moduleWrapper}>
|
||||||
<div className={styles.moduleHeader}>{t('common.addComment')}</div>
|
<Icon name="comment outline" className={styles.moduleIcon} />
|
||||||
<CommentAdd onCreate={onCommentCreate} />
|
<div className={styles.moduleHeader}>{t('common.addComment')}</div>
|
||||||
|
<CommentAdd onCreate={onCommentCreate} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
<div className={styles.contentModule}>
|
<div className={styles.contentModule}>
|
||||||
<div className={styles.moduleWrapper}>
|
<div className={styles.moduleWrapper}>
|
||||||
<Icon name="list ul" className={styles.moduleIcon} />
|
<Icon name="list ul" className={styles.moduleIcon} />
|
||||||
|
@ -59,7 +62,7 @@ const Actions = React.memo(
|
||||||
createdAt={item.createdAt}
|
createdAt={item.createdAt}
|
||||||
isPersisted={item.isPersisted}
|
isPersisted={item.isPersisted}
|
||||||
user={item.user}
|
user={item.user}
|
||||||
isEditable={isEditable}
|
canEdit={(item.user.isCurrent && canEdit) || canEditAllComments}
|
||||||
onUpdate={(data) => handleCommentUpdate(item.id, data)}
|
onUpdate={(data) => handleCommentUpdate(item.id, data)}
|
||||||
onDelete={() => handleCommentDelete(item.id)}
|
onDelete={() => handleCommentDelete(item.id)}
|
||||||
/>
|
/>
|
||||||
|
@ -91,7 +94,8 @@ Actions.propTypes = {
|
||||||
items: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
items: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
isFetching: PropTypes.bool.isRequired,
|
isFetching: PropTypes.bool.isRequired,
|
||||||
isAllFetched: PropTypes.bool.isRequired,
|
isAllFetched: PropTypes.bool.isRequired,
|
||||||
isEditable: PropTypes.bool.isRequired,
|
canEdit: PropTypes.bool.isRequired,
|
||||||
|
canEditAllComments: PropTypes.bool.isRequired,
|
||||||
onFetch: PropTypes.func.isRequired,
|
onFetch: PropTypes.func.isRequired,
|
||||||
onCommentCreate: PropTypes.func.isRequired,
|
onCommentCreate: PropTypes.func.isRequired,
|
||||||
onCommentUpdate: PropTypes.func.isRequired,
|
onCommentUpdate: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import DeletePopup from '../../DeletePopup';
|
||||||
import styles from './ItemComment.module.scss';
|
import styles from './ItemComment.module.scss';
|
||||||
|
|
||||||
const ItemComment = React.memo(
|
const ItemComment = React.memo(
|
||||||
({ data, createdAt, isPersisted, user, isEditable, onUpdate, onDelete }) => {
|
({ data, createdAt, isPersisted, user, canEdit, onUpdate, onDelete }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
const commentEdit = useRef(null);
|
const commentEdit = useRef(null);
|
||||||
|
@ -38,17 +38,17 @@ const ItemComment = React.memo(
|
||||||
</div>
|
</div>
|
||||||
<CommentEdit ref={commentEdit} defaultData={data} onUpdate={onUpdate}>
|
<CommentEdit ref={commentEdit} defaultData={data} onUpdate={onUpdate}>
|
||||||
<>
|
<>
|
||||||
<Markdown source={data.text} linkTarget="_blank" className={styles.text} />
|
<Markdown linkTarget="_blank" className={styles.text}>
|
||||||
<Comment.Actions>
|
{data.text}
|
||||||
{user.isCurrent && (
|
</Markdown>
|
||||||
|
{canEdit && (
|
||||||
|
<Comment.Actions>
|
||||||
<Comment.Action
|
<Comment.Action
|
||||||
as="button"
|
as="button"
|
||||||
content={t('action.edit')}
|
content={t('action.edit')}
|
||||||
disabled={!isPersisted}
|
disabled={!isPersisted}
|
||||||
onClick={handleEditClick}
|
onClick={handleEditClick}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
{(user.isCurrent || isEditable) && (
|
|
||||||
<DeletePopup
|
<DeletePopup
|
||||||
title={t('common.deleteComment', {
|
title={t('common.deleteComment', {
|
||||||
context: 'title',
|
context: 'title',
|
||||||
|
@ -63,8 +63,8 @@ const ItemComment = React.memo(
|
||||||
disabled={!isPersisted}
|
disabled={!isPersisted}
|
||||||
/>
|
/>
|
||||||
</DeletePopup>
|
</DeletePopup>
|
||||||
)}
|
</Comment.Actions>
|
||||||
</Comment.Actions>
|
)}
|
||||||
</>
|
</>
|
||||||
</CommentEdit>
|
</CommentEdit>
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,7 +78,7 @@ ItemComment.propTypes = {
|
||||||
createdAt: PropTypes.instanceOf(Date).isRequired,
|
createdAt: PropTypes.instanceOf(Date).isRequired,
|
||||||
isPersisted: PropTypes.bool.isRequired,
|
isPersisted: PropTypes.bool.isRequired,
|
||||||
user: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
|
user: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
isEditable: PropTypes.bool.isRequired,
|
canEdit: PropTypes.bool.isRequired,
|
||||||
onUpdate: PropTypes.func.isRequired,
|
onUpdate: PropTypes.func.isRequired,
|
||||||
onDelete: PropTypes.func.isRequired,
|
onDelete: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 1;
|
z-index: 2000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import User from '../User';
|
||||||
import Label from '../Label';
|
import Label from '../Label';
|
||||||
import DueDate from '../DueDate';
|
import DueDate from '../DueDate';
|
||||||
import Timer from '../Timer';
|
import Timer from '../Timer';
|
||||||
import ProjectMembershipsPopup from '../ProjectMembershipsPopup';
|
import BoardMembershipsPopup from '../BoardMembershipsPopup';
|
||||||
import LabelsPopup from '../LabelsPopup';
|
import LabelsPopup from '../LabelsPopup';
|
||||||
import DueDateEditPopup from '../DueDateEditPopup';
|
import DueDateEditPopup from '../DueDateEditPopup';
|
||||||
import TimerEditPopup from '../TimerEditPopup';
|
import TimerEditPopup from '../TimerEditPopup';
|
||||||
|
@ -43,9 +43,10 @@ const CardModal = React.memo(
|
||||||
attachments,
|
attachments,
|
||||||
actions,
|
actions,
|
||||||
allProjectsToLists,
|
allProjectsToLists,
|
||||||
allProjectMemberships,
|
allBoardMemberships,
|
||||||
allLabels,
|
allLabels,
|
||||||
isEditable,
|
canEdit,
|
||||||
|
canEditAllCommentActions,
|
||||||
onUpdate,
|
onUpdate,
|
||||||
onMove,
|
onMove,
|
||||||
onTransfer,
|
onTransfer,
|
||||||
|
@ -126,137 +127,163 @@ const CardModal = React.memo(
|
||||||
const userIds = users.map((user) => user.id);
|
const userIds = users.map((user) => user.id);
|
||||||
const labelIds = labels.map((label) => label.id);
|
const labelIds = labels.map((label) => label.id);
|
||||||
|
|
||||||
return (
|
const contentNode = (
|
||||||
<Modal open closeIcon size="small" centered={false} onClose={onClose}>
|
<Grid className={styles.grid}>
|
||||||
<AttachmentAddZone onCreate={onAttachmentCreate}>
|
<Grid.Row className={styles.headerPadding}>
|
||||||
<Grid className={styles.grid}>
|
<Grid.Column width={16} className={styles.headerPadding}>
|
||||||
<Grid.Row className={styles.headerPadding}>
|
<div className={styles.headerWrapper}>
|
||||||
<Grid.Column width={16} className={styles.headerPadding}>
|
<Icon name="list alternate outline" className={styles.moduleIcon} />
|
||||||
<div className={styles.headerWrapper}>
|
<div className={styles.headerTitleWrapper}>
|
||||||
<Icon name="list alternate outline" className={styles.moduleIcon} />
|
{canEdit ? (
|
||||||
<div className={styles.headerTitle}>
|
<NameField defaultValue={name} onUpdate={handleNameUpdate} />
|
||||||
<NameField defaultValue={name} onUpdate={handleNameUpdate} />
|
) : (
|
||||||
</div>
|
<div className={styles.headerTitle}>{name}</div>
|
||||||
</div>
|
)}
|
||||||
</Grid.Column>
|
</div>
|
||||||
</Grid.Row>
|
</div>
|
||||||
<Grid.Row className={styles.modalPadding}>
|
</Grid.Column>
|
||||||
<Grid.Column width={12} className={styles.contentPadding}>
|
</Grid.Row>
|
||||||
{(users.length > 0 || labels.length > 0 || dueDate || timer) && (
|
<Grid.Row className={styles.modalPadding}>
|
||||||
<div className={styles.moduleWrapper}>
|
<Grid.Column width={canEdit ? 12 : 16} className={styles.contentPadding}>
|
||||||
{users.length > 0 && (
|
{(users.length > 0 || labels.length > 0 || dueDate || timer) && (
|
||||||
<div className={styles.attachments}>
|
<div className={styles.moduleWrapper}>
|
||||||
<div className={styles.text}>
|
{users.length > 0 && (
|
||||||
{t('common.members', {
|
<div className={styles.attachments}>
|
||||||
context: 'title',
|
<div className={styles.text}>
|
||||||
})}
|
{t('common.members', {
|
||||||
</div>
|
context: 'title',
|
||||||
{users.map((user) => (
|
})}
|
||||||
<span key={user.id} className={styles.attachment}>
|
</div>
|
||||||
<ProjectMembershipsPopup
|
{users.map((user) => (
|
||||||
items={allProjectMemberships}
|
<span key={user.id} className={styles.attachment}>
|
||||||
currentUserIds={userIds}
|
{canEdit ? (
|
||||||
onUserSelect={onUserAdd}
|
<BoardMembershipsPopup
|
||||||
onUserDeselect={onUserRemove}
|
items={allBoardMemberships}
|
||||||
>
|
currentUserIds={userIds}
|
||||||
<User name={user.name} avatarUrl={user.avatarUrl} />
|
onUserSelect={onUserAdd}
|
||||||
</ProjectMembershipsPopup>
|
onUserDeselect={onUserRemove}
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
<ProjectMembershipsPopup
|
|
||||||
items={allProjectMemberships}
|
|
||||||
currentUserIds={userIds}
|
|
||||||
onUserSelect={onUserAdd}
|
|
||||||
onUserDeselect={onUserRemove}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className={classNames(styles.attachment, styles.dueDate)}
|
|
||||||
>
|
>
|
||||||
<Icon name="add" size="small" className={styles.addAttachment} />
|
<User name={user.name} avatarUrl={user.avatarUrl} />
|
||||||
</button>
|
</BoardMembershipsPopup>
|
||||||
</ProjectMembershipsPopup>
|
) : (
|
||||||
</div>
|
<User name={user.name} avatarUrl={user.avatarUrl} />
|
||||||
)}
|
)}
|
||||||
{labels.length > 0 && (
|
</span>
|
||||||
<div className={styles.attachments}>
|
))}
|
||||||
<div className={styles.text}>
|
{canEdit && (
|
||||||
{t('common.labels', {
|
<BoardMembershipsPopup
|
||||||
context: 'title',
|
items={allBoardMemberships}
|
||||||
})}
|
currentUserIds={userIds}
|
||||||
</div>
|
onUserSelect={onUserAdd}
|
||||||
{labels.map((label) => (
|
onUserDeselect={onUserRemove}
|
||||||
<span key={label.id} className={styles.attachment}>
|
>
|
||||||
<LabelsPopup
|
<button
|
||||||
key={label.id}
|
type="button"
|
||||||
items={allLabels}
|
className={classNames(styles.attachment, styles.dueDate)}
|
||||||
currentIds={labelIds}
|
|
||||||
onSelect={onLabelAdd}
|
|
||||||
onDeselect={onLabelRemove}
|
|
||||||
onCreate={onLabelCreate}
|
|
||||||
onUpdate={onLabelUpdate}
|
|
||||||
onDelete={onLabelDelete}
|
|
||||||
>
|
|
||||||
<Label name={label.name} color={label.color} />
|
|
||||||
</LabelsPopup>
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
<LabelsPopup
|
|
||||||
items={allLabels}
|
|
||||||
currentIds={labelIds}
|
|
||||||
onSelect={onLabelAdd}
|
|
||||||
onDeselect={onLabelRemove}
|
|
||||||
onCreate={onLabelCreate}
|
|
||||||
onUpdate={onLabelUpdate}
|
|
||||||
onDelete={onLabelDelete}
|
|
||||||
>
|
>
|
||||||
<button
|
<Icon name="add" size="small" className={styles.addAttachment} />
|
||||||
type="button"
|
</button>
|
||||||
className={classNames(styles.attachment, styles.dueDate)}
|
</BoardMembershipsPopup>
|
||||||
>
|
|
||||||
<Icon name="add" size="small" className={styles.addAttachment} />
|
|
||||||
</button>
|
|
||||||
</LabelsPopup>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{dueDate && (
|
|
||||||
<div className={styles.attachments}>
|
|
||||||
<div className={styles.text}>
|
|
||||||
{t('common.dueDate', {
|
|
||||||
context: 'title',
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<span className={styles.attachment}>
|
|
||||||
<DueDateEditPopup defaultValue={dueDate} onUpdate={handleDueDateUpdate}>
|
|
||||||
<DueDate value={dueDate} />
|
|
||||||
</DueDateEditPopup>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{timer && (
|
|
||||||
<div className={styles.attachments}>
|
|
||||||
<div className={styles.text}>
|
|
||||||
{t('common.timer', {
|
|
||||||
context: 'title',
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<span className={styles.attachment}>
|
|
||||||
<TimerEditPopup defaultValue={timer} onUpdate={handleTimerUpdate}>
|
|
||||||
<Timer startedAt={timer.startedAt} total={timer.total} />
|
|
||||||
</TimerEditPopup>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={styles.contentModule}>
|
{labels.length > 0 && (
|
||||||
<div className={styles.moduleWrapper}>
|
<div className={styles.attachments}>
|
||||||
<Icon name="align justify" className={styles.moduleIcon} />
|
<div className={styles.text}>
|
||||||
<div className={styles.moduleHeader}>{t('common.description')}</div>
|
{t('common.labels', {
|
||||||
|
context: 'title',
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
{labels.map((label) => (
|
||||||
|
<span key={label.id} className={styles.attachment}>
|
||||||
|
{canEdit ? (
|
||||||
|
<LabelsPopup
|
||||||
|
key={label.id}
|
||||||
|
items={allLabels}
|
||||||
|
currentIds={labelIds}
|
||||||
|
onSelect={onLabelAdd}
|
||||||
|
onDeselect={onLabelRemove}
|
||||||
|
onCreate={onLabelCreate}
|
||||||
|
onUpdate={onLabelUpdate}
|
||||||
|
onDelete={onLabelDelete}
|
||||||
|
>
|
||||||
|
<Label name={label.name} color={label.color} />
|
||||||
|
</LabelsPopup>
|
||||||
|
) : (
|
||||||
|
<Label name={label.name} color={label.color} />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
{canEdit && (
|
||||||
|
<LabelsPopup
|
||||||
|
items={allLabels}
|
||||||
|
currentIds={labelIds}
|
||||||
|
onSelect={onLabelAdd}
|
||||||
|
onDeselect={onLabelRemove}
|
||||||
|
onCreate={onLabelCreate}
|
||||||
|
onUpdate={onLabelUpdate}
|
||||||
|
onDelete={onLabelDelete}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={classNames(styles.attachment, styles.dueDate)}
|
||||||
|
>
|
||||||
|
<Icon name="add" size="small" className={styles.addAttachment} />
|
||||||
|
</button>
|
||||||
|
</LabelsPopup>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{dueDate && (
|
||||||
|
<div className={styles.attachments}>
|
||||||
|
<div className={styles.text}>
|
||||||
|
{t('common.dueDate', {
|
||||||
|
context: 'title',
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<span className={styles.attachment}>
|
||||||
|
{canEdit ? (
|
||||||
|
<DueDateEditPopup defaultValue={dueDate} onUpdate={handleDueDateUpdate}>
|
||||||
|
<DueDate value={dueDate} />
|
||||||
|
</DueDateEditPopup>
|
||||||
|
) : (
|
||||||
|
<DueDate value={dueDate} />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{timer && (
|
||||||
|
<div className={styles.attachments}>
|
||||||
|
<div className={styles.text}>
|
||||||
|
{t('common.timer', {
|
||||||
|
context: 'title',
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<span className={styles.attachment}>
|
||||||
|
{canEdit ? (
|
||||||
|
<TimerEditPopup defaultValue={timer} onUpdate={handleTimerUpdate}>
|
||||||
|
<Timer startedAt={timer.startedAt} total={timer.total} />
|
||||||
|
</TimerEditPopup>
|
||||||
|
) : (
|
||||||
|
<Timer startedAt={timer.startedAt} total={timer.total} />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{(description || canEdit) && (
|
||||||
|
<div className={styles.contentModule}>
|
||||||
|
<div className={styles.moduleWrapper}>
|
||||||
|
<Icon name="align justify" className={styles.moduleIcon} />
|
||||||
|
<div className={styles.moduleHeader}>{t('common.description')}</div>
|
||||||
|
{canEdit ? (
|
||||||
<DescriptionEdit defaultValue={description} onUpdate={handleDescriptionUpdate}>
|
<DescriptionEdit defaultValue={description} onUpdate={handleDescriptionUpdate}>
|
||||||
{description ? (
|
{description ? (
|
||||||
<button type="button" className={styles.descriptionText}>
|
<button type="button" className={styles.descriptionText}>
|
||||||
<Markdown linkStopPropagation source={description} linkTarget="_blank" />
|
<Markdown linkStopPropagation linkTarget="_blank">
|
||||||
|
{description}
|
||||||
|
</Markdown>
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button type="button" className={styles.descriptionButton}>
|
<button type="button" className={styles.descriptionButton}>
|
||||||
|
@ -266,142 +293,164 @@ const CardModal = React.memo(
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</DescriptionEdit>
|
</DescriptionEdit>
|
||||||
</div>
|
) : (
|
||||||
</div>
|
<div className={styles.descriptionText}>
|
||||||
<div className={styles.contentModule}>
|
<Markdown linkStopPropagation linkTarget="_blank">
|
||||||
<div className={styles.moduleWrapper}>
|
{description}
|
||||||
<Icon name="check square outline" className={styles.moduleIcon} />
|
</Markdown>
|
||||||
<div className={styles.moduleHeader}>{t('common.tasks')}</div>
|
|
||||||
<Tasks
|
|
||||||
items={tasks}
|
|
||||||
onCreate={onTaskCreate}
|
|
||||||
onUpdate={onTaskUpdate}
|
|
||||||
onDelete={onTaskDelete}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{attachments.length > 0 && (
|
|
||||||
<div className={styles.contentModule}>
|
|
||||||
<div className={styles.moduleWrapper}>
|
|
||||||
<Icon name="attach" className={styles.moduleIcon} />
|
|
||||||
<div className={styles.moduleHeader}>{t('common.attachments')}</div>
|
|
||||||
<Attachments
|
|
||||||
items={attachments}
|
|
||||||
onUpdate={onAttachmentUpdate}
|
|
||||||
onDelete={onAttachmentDelete}
|
|
||||||
onCoverUpdate={handleCoverUpdate}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
|
||||||
<Actions
|
|
||||||
items={actions}
|
|
||||||
isFetching={isActionsFetching}
|
|
||||||
isAllFetched={isAllActionsFetched}
|
|
||||||
isEditable={isEditable}
|
|
||||||
onFetch={onActionsFetch}
|
|
||||||
onCommentCreate={onCommentActionCreate}
|
|
||||||
onCommentUpdate={onCommentActionUpdate}
|
|
||||||
onCommentDelete={onCommentActionDelete}
|
|
||||||
/>
|
|
||||||
</Grid.Column>
|
|
||||||
<Grid.Column width={4} className={styles.sidebarPadding}>
|
|
||||||
<div className={styles.actions}>
|
|
||||||
<span className={styles.actionsTitle}>{t('action.addToCard')}</span>
|
|
||||||
<ProjectMembershipsPopup
|
|
||||||
items={allProjectMemberships}
|
|
||||||
currentUserIds={userIds}
|
|
||||||
onUserSelect={onUserAdd}
|
|
||||||
onUserDeselect={onUserRemove}
|
|
||||||
>
|
|
||||||
<Button fluid className={styles.actionButton}>
|
|
||||||
<Icon name="user outline" className={styles.actionIcon} />
|
|
||||||
{t('common.members')}
|
|
||||||
</Button>
|
|
||||||
</ProjectMembershipsPopup>
|
|
||||||
<LabelsPopup
|
|
||||||
items={allLabels}
|
|
||||||
currentIds={labelIds}
|
|
||||||
onSelect={onLabelAdd}
|
|
||||||
onDeselect={onLabelRemove}
|
|
||||||
onCreate={onLabelCreate}
|
|
||||||
onUpdate={onLabelUpdate}
|
|
||||||
onDelete={onLabelDelete}
|
|
||||||
>
|
|
||||||
<Button fluid className={styles.actionButton}>
|
|
||||||
<Icon name="bookmark outline" className={styles.actionIcon} />
|
|
||||||
{t('common.labels')}
|
|
||||||
</Button>
|
|
||||||
</LabelsPopup>
|
|
||||||
<DueDateEditPopup defaultValue={dueDate} onUpdate={handleDueDateUpdate}>
|
|
||||||
<Button fluid className={styles.actionButton}>
|
|
||||||
<Icon name="calendar check outline" className={styles.actionIcon} />
|
|
||||||
{t('common.dueDate', {
|
|
||||||
context: 'title',
|
|
||||||
})}
|
|
||||||
</Button>
|
|
||||||
</DueDateEditPopup>
|
|
||||||
<TimerEditPopup defaultValue={timer} onUpdate={handleTimerUpdate}>
|
|
||||||
<Button fluid className={styles.actionButton}>
|
|
||||||
<Icon name="clock outline" className={styles.actionIcon} />
|
|
||||||
{t('common.timer')}
|
|
||||||
</Button>
|
|
||||||
</TimerEditPopup>
|
|
||||||
<AttachmentAddPopup onCreate={onAttachmentCreate}>
|
|
||||||
<Button fluid className={styles.actionButton}>
|
|
||||||
<Icon name="attach" className={styles.actionIcon} />
|
|
||||||
{t('common.attachment')}
|
|
||||||
</Button>
|
|
||||||
</AttachmentAddPopup>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.actions}>
|
</div>
|
||||||
<span className={styles.actionsTitle}>{t('common.actions')}</span>
|
)}
|
||||||
|
{(tasks.length > 0 || canEdit) && (
|
||||||
|
<div className={styles.contentModule}>
|
||||||
|
<div className={styles.moduleWrapper}>
|
||||||
|
<Icon name="check square outline" className={styles.moduleIcon} />
|
||||||
|
<div className={styles.moduleHeader}>{t('common.tasks')}</div>
|
||||||
|
<Tasks
|
||||||
|
items={tasks}
|
||||||
|
canEdit={canEdit}
|
||||||
|
onCreate={onTaskCreate}
|
||||||
|
onUpdate={onTaskUpdate}
|
||||||
|
onDelete={onTaskDelete}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{attachments.length > 0 && (
|
||||||
|
<div className={styles.contentModule}>
|
||||||
|
<div className={styles.moduleWrapper}>
|
||||||
|
<Icon name="attach" className={styles.moduleIcon} />
|
||||||
|
<div className={styles.moduleHeader}>{t('common.attachments')}</div>
|
||||||
|
<Attachments
|
||||||
|
items={attachments}
|
||||||
|
onUpdate={onAttachmentUpdate}
|
||||||
|
onDelete={onAttachmentDelete}
|
||||||
|
onCoverUpdate={handleCoverUpdate}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<Actions
|
||||||
|
items={actions}
|
||||||
|
isFetching={isActionsFetching}
|
||||||
|
isAllFetched={isAllActionsFetched}
|
||||||
|
canEdit={canEdit}
|
||||||
|
canEditAllComments={canEditAllCommentActions}
|
||||||
|
onFetch={onActionsFetch}
|
||||||
|
onCommentCreate={onCommentActionCreate}
|
||||||
|
onCommentUpdate={onCommentActionUpdate}
|
||||||
|
onCommentDelete={onCommentActionDelete}
|
||||||
|
/>
|
||||||
|
</Grid.Column>
|
||||||
|
{canEdit && (
|
||||||
|
<Grid.Column width={4} className={styles.sidebarPadding}>
|
||||||
|
<div className={styles.actions}>
|
||||||
|
<span className={styles.actionsTitle}>{t('action.addToCard')}</span>
|
||||||
|
<BoardMembershipsPopup
|
||||||
|
items={allBoardMemberships}
|
||||||
|
currentUserIds={userIds}
|
||||||
|
onUserSelect={onUserAdd}
|
||||||
|
onUserDeselect={onUserRemove}
|
||||||
|
>
|
||||||
|
<Button fluid className={styles.actionButton}>
|
||||||
|
<Icon name="user outline" className={styles.actionIcon} />
|
||||||
|
{t('common.members')}
|
||||||
|
</Button>
|
||||||
|
</BoardMembershipsPopup>
|
||||||
|
<LabelsPopup
|
||||||
|
items={allLabels}
|
||||||
|
currentIds={labelIds}
|
||||||
|
onSelect={onLabelAdd}
|
||||||
|
onDeselect={onLabelRemove}
|
||||||
|
onCreate={onLabelCreate}
|
||||||
|
onUpdate={onLabelUpdate}
|
||||||
|
onDelete={onLabelDelete}
|
||||||
|
>
|
||||||
|
<Button fluid className={styles.actionButton}>
|
||||||
|
<Icon name="bookmark outline" className={styles.actionIcon} />
|
||||||
|
{t('common.labels')}
|
||||||
|
</Button>
|
||||||
|
</LabelsPopup>
|
||||||
|
<DueDateEditPopup defaultValue={dueDate} onUpdate={handleDueDateUpdate}>
|
||||||
|
<Button fluid className={styles.actionButton}>
|
||||||
|
<Icon name="calendar check outline" className={styles.actionIcon} />
|
||||||
|
{t('common.dueDate', {
|
||||||
|
context: 'title',
|
||||||
|
})}
|
||||||
|
</Button>
|
||||||
|
</DueDateEditPopup>
|
||||||
|
<TimerEditPopup defaultValue={timer} onUpdate={handleTimerUpdate}>
|
||||||
|
<Button fluid className={styles.actionButton}>
|
||||||
|
<Icon name="clock outline" className={styles.actionIcon} />
|
||||||
|
{t('common.timer')}
|
||||||
|
</Button>
|
||||||
|
</TimerEditPopup>
|
||||||
|
<AttachmentAddPopup onCreate={onAttachmentCreate}>
|
||||||
|
<Button fluid className={styles.actionButton}>
|
||||||
|
<Icon name="attach" className={styles.actionIcon} />
|
||||||
|
{t('common.attachment')}
|
||||||
|
</Button>
|
||||||
|
</AttachmentAddPopup>
|
||||||
|
</div>
|
||||||
|
<div className={styles.actions}>
|
||||||
|
<span className={styles.actionsTitle}>{t('common.actions')}</span>
|
||||||
|
<Button
|
||||||
|
fluid
|
||||||
|
className={styles.actionButton}
|
||||||
|
onClick={handleToggleSubscriptionClick}
|
||||||
|
>
|
||||||
|
<Icon name="paper plane outline" className={styles.actionIcon} />
|
||||||
|
{isSubscribed ? t('action.unsubscribe') : t('action.subscribe')}
|
||||||
|
</Button>
|
||||||
|
<CardMovePopup
|
||||||
|
projectsToLists={allProjectsToLists}
|
||||||
|
defaultPath={{
|
||||||
|
projectId,
|
||||||
|
boardId,
|
||||||
|
listId,
|
||||||
|
}}
|
||||||
|
onMove={onMove}
|
||||||
|
onTransfer={onTransfer}
|
||||||
|
onBoardFetch={onBoardFetch}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
fluid
|
fluid
|
||||||
className={styles.actionButton}
|
className={styles.actionButton}
|
||||||
onClick={handleToggleSubscriptionClick}
|
onClick={handleToggleSubscriptionClick}
|
||||||
>
|
>
|
||||||
<Icon name="paper plane outline" className={styles.actionIcon} />
|
<Icon name="share square outline" className={styles.actionIcon} />
|
||||||
{isSubscribed ? t('action.unsubscribe') : t('action.subscribe')}
|
{t('action.move')}
|
||||||
</Button>
|
</Button>
|
||||||
<CardMovePopup
|
</CardMovePopup>
|
||||||
projectsToLists={allProjectsToLists}
|
<DeletePopup
|
||||||
defaultPath={{
|
title={t('common.deleteCard', {
|
||||||
projectId,
|
context: 'title',
|
||||||
boardId,
|
})}
|
||||||
listId,
|
content={t('common.areYouSureYouWantToDeleteThisCard')}
|
||||||
}}
|
buttonContent={t('action.deleteCard')}
|
||||||
onMove={onMove}
|
onConfirm={onDelete}
|
||||||
onTransfer={onTransfer}
|
>
|
||||||
onBoardFetch={onBoardFetch}
|
<Button fluid className={styles.actionButton}>
|
||||||
>
|
<Icon name="trash alternate outline" className={styles.actionIcon} />
|
||||||
<Button
|
{t('action.delete')}
|
||||||
fluid
|
</Button>
|
||||||
className={styles.actionButton}
|
</DeletePopup>
|
||||||
onClick={handleToggleSubscriptionClick}
|
</div>
|
||||||
>
|
</Grid.Column>
|
||||||
<Icon name="share square outline" className={styles.actionIcon} />
|
)}
|
||||||
{t('action.move')}
|
</Grid.Row>
|
||||||
</Button>
|
</Grid>
|
||||||
</CardMovePopup>
|
);
|
||||||
<DeletePopup
|
|
||||||
title={t('common.deleteCard', {
|
return (
|
||||||
context: 'title',
|
<Modal open closeIcon size="small" centered={false} onClose={onClose}>
|
||||||
})}
|
{canEdit ? (
|
||||||
content={t('common.areYouSureYouWantToDeleteThisCard')}
|
<AttachmentAddZone onCreate={onAttachmentCreate}>{contentNode}</AttachmentAddZone>
|
||||||
buttonContent={t('action.deleteCard')}
|
) : (
|
||||||
onConfirm={onDelete}
|
contentNode
|
||||||
>
|
)}
|
||||||
<Button fluid className={styles.actionButton}>
|
|
||||||
<Icon name="trash alternate outline" className={styles.actionIcon} />
|
|
||||||
{t('action.delete')}
|
|
||||||
</Button>
|
|
||||||
</DeletePopup>
|
|
||||||
</div>
|
|
||||||
</Grid.Column>
|
|
||||||
</Grid.Row>
|
|
||||||
</Grid>
|
|
||||||
</AttachmentAddZone>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -425,10 +474,11 @@ CardModal.propTypes = {
|
||||||
attachments: PropTypes.array.isRequired,
|
attachments: PropTypes.array.isRequired,
|
||||||
actions: PropTypes.array.isRequired,
|
actions: PropTypes.array.isRequired,
|
||||||
allProjectsToLists: PropTypes.array.isRequired,
|
allProjectsToLists: PropTypes.array.isRequired,
|
||||||
allProjectMemberships: PropTypes.array.isRequired,
|
allBoardMemberships: PropTypes.array.isRequired,
|
||||||
allLabels: PropTypes.array.isRequired,
|
allLabels: PropTypes.array.isRequired,
|
||||||
/* eslint-enable react/forbid-prop-types */
|
/* eslint-enable react/forbid-prop-types */
|
||||||
isEditable: PropTypes.bool.isRequired,
|
canEdit: PropTypes.bool.isRequired,
|
||||||
|
canEditAllCommentActions: PropTypes.bool.isRequired,
|
||||||
onUpdate: PropTypes.func.isRequired,
|
onUpdate: PropTypes.func.isRequired,
|
||||||
onMove: PropTypes.func.isRequired,
|
onMove: PropTypes.func.isRequired,
|
||||||
onTransfer: PropTypes.func.isRequired,
|
onTransfer: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachment {
|
.attachment {
|
||||||
cursor: pointer;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0 4px 4px 0;
|
margin: 0 4px 4px 0;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
@ -70,6 +69,7 @@
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
color: #6b808c;
|
color: #6b808c;
|
||||||
|
cursor: pointer;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
outline: none;
|
outline: none;
|
||||||
padding: 6px 14px;
|
padding: 6px 14px;
|
||||||
|
@ -141,6 +141,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.headerTitle {
|
.headerTitle {
|
||||||
|
color: #17394d;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerTitleWrapper {
|
||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
padding: 6px 0 0;
|
padding: 6px 0 0;
|
||||||
}
|
}
|
||||||
|
@ -193,8 +200,4 @@
|
||||||
margin: 0 8px 4px 0;
|
margin: 0 8px 4px 0;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .wrapper {
|
|
||||||
min-width: 768px;
|
|
||||||
} */
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,14 +8,14 @@ import ActionsPopup from './ActionsPopup';
|
||||||
|
|
||||||
import styles from './Item.module.scss';
|
import styles from './Item.module.scss';
|
||||||
|
|
||||||
const Item = React.memo(({ name, isCompleted, isPersisted, onUpdate, onDelete }) => {
|
const Item = React.memo(({ name, isCompleted, isPersisted, canEdit, onUpdate, onDelete }) => {
|
||||||
const nameEdit = useRef(null);
|
const nameEdit = useRef(null);
|
||||||
|
|
||||||
const handleClick = useCallback(() => {
|
const handleClick = useCallback(() => {
|
||||||
if (isPersisted) {
|
if (isPersisted && canEdit) {
|
||||||
nameEdit.current.open();
|
nameEdit.current.open();
|
||||||
}
|
}
|
||||||
}, [isPersisted]);
|
}, [isPersisted, canEdit]);
|
||||||
|
|
||||||
const handleNameUpdate = useCallback(
|
const handleNameUpdate = useCallback(
|
||||||
(newName) => {
|
(newName) => {
|
||||||
|
@ -41,23 +41,26 @@ const Item = React.memo(({ name, isCompleted, isPersisted, onUpdate, onDelete })
|
||||||
<span className={styles.checkboxWrapper}>
|
<span className={styles.checkboxWrapper}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={isCompleted}
|
checked={isCompleted}
|
||||||
disabled={!isPersisted}
|
disabled={!isPersisted || !canEdit}
|
||||||
className={styles.checkbox}
|
className={styles.checkbox}
|
||||||
onChange={handleToggleChange}
|
onChange={handleToggleChange}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<NameEdit ref={nameEdit} defaultValue={name} onUpdate={handleNameUpdate}>
|
<NameEdit ref={nameEdit} defaultValue={name} onUpdate={handleNameUpdate}>
|
||||||
<div className={styles.content}>
|
<div className={classNames(canEdit && styles.contentHoverable)}>
|
||||||
{/* eslint-disable jsx-a11y/click-events-have-key-events,
|
{/* eslint-disable jsx-a11y/click-events-have-key-events,
|
||||||
jsx-a11y/no-static-element-interactions */}
|
jsx-a11y/no-static-element-interactions */}
|
||||||
<span className={styles.text} onClick={handleClick}>
|
<span
|
||||||
|
className={classNames(styles.text, canEdit && styles.textEditable)}
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
{/* eslint-enable jsx-a11y/click-events-have-key-events,
|
{/* eslint-enable jsx-a11y/click-events-have-key-events,
|
||||||
jsx-a11y/no-static-element-interactions */}
|
jsx-a11y/no-static-element-interactions */}
|
||||||
<span className={classNames(styles.task, isCompleted && styles.taskCompleted)}>
|
<span className={classNames(styles.task, isCompleted && styles.taskCompleted)}>
|
||||||
{name}
|
{name}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
{isPersisted && (
|
{isPersisted && canEdit && (
|
||||||
<ActionsPopup onNameEdit={handleNameEdit} onDelete={onDelete}>
|
<ActionsPopup onNameEdit={handleNameEdit} onDelete={onDelete}>
|
||||||
<Button className={classNames(styles.button, styles.target)}>
|
<Button className={classNames(styles.button, styles.target)}>
|
||||||
<Icon fitted name="pencil" size="small" />
|
<Icon fitted name="pencil" size="small" />
|
||||||
|
@ -74,6 +77,7 @@ Item.propTypes = {
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
isCompleted: PropTypes.bool.isRequired,
|
isCompleted: PropTypes.bool.isRequired,
|
||||||
isPersisted: PropTypes.bool.isRequired,
|
isPersisted: PropTypes.bool.isRequired,
|
||||||
|
canEdit: PropTypes.bool.isRequired,
|
||||||
onUpdate: PropTypes.func.isRequired,
|
onUpdate: PropTypes.func.isRequired,
|
||||||
onDelete: PropTypes.func.isRequired,
|
onDelete: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
height: 32px;
|
height: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content:hover {
|
.contentHoverable:hover {
|
||||||
background: rgba(9, 30, 66, 0.04);
|
background: rgba(9, 30, 66, 0.04);
|
||||||
|
|
||||||
.target {
|
.target {
|
||||||
|
@ -55,7 +55,6 @@
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
color: #17394d;
|
color: #17394d;
|
||||||
cursor: pointer;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
@ -64,6 +63,10 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.textEditable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
margin-left: -40px;
|
margin-left: -40px;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import Add from './Add';
|
||||||
|
|
||||||
import styles from './Tasks.module.scss';
|
import styles from './Tasks.module.scss';
|
||||||
|
|
||||||
const Tasks = React.memo(({ items, onCreate, onUpdate, onDelete }) => {
|
const Tasks = React.memo(({ items, canEdit, onCreate, onUpdate, onDelete }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
const handleUpdate = useCallback(
|
const handleUpdate = useCallback(
|
||||||
|
@ -45,23 +45,27 @@ const Tasks = React.memo(({ items, onCreate, onUpdate, onDelete }) => {
|
||||||
name={item.name}
|
name={item.name}
|
||||||
isCompleted={item.isCompleted}
|
isCompleted={item.isCompleted}
|
||||||
isPersisted={item.isPersisted}
|
isPersisted={item.isPersisted}
|
||||||
|
canEdit={canEdit}
|
||||||
onUpdate={(data) => handleUpdate(item.id, data)}
|
onUpdate={(data) => handleUpdate(item.id, data)}
|
||||||
onDelete={() => handleDelete(item.id)}
|
onDelete={() => handleDelete(item.id)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<Add onCreate={onCreate}>
|
{canEdit && (
|
||||||
<button type="button" className={styles.taskButton}>
|
<Add onCreate={onCreate}>
|
||||||
<span className={styles.taskButtonText}>
|
<button type="button" className={styles.taskButton}>
|
||||||
{items.length > 0 ? t('action.addAnotherTask') : t('action.addTask')}
|
<span className={styles.taskButtonText}>
|
||||||
</span>
|
{items.length > 0 ? t('action.addAnotherTask') : t('action.addTask')}
|
||||||
</button>
|
</span>
|
||||||
</Add>
|
</button>
|
||||||
|
</Add>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Tasks.propTypes = {
|
Tasks.propTypes = {
|
||||||
items: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
items: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
|
canEdit: PropTypes.bool.isRequired,
|
||||||
onCreate: PropTypes.func.isRequired,
|
onCreate: PropTypes.func.isRequired,
|
||||||
onUpdate: PropTypes.func.isRequired,
|
onUpdate: PropTypes.func.isRequired,
|
||||||
onDelete: PropTypes.func.isRequired,
|
onDelete: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Loader } from 'semantic-ui-react';
|
|
||||||
|
|
||||||
import CoreContainer from '../containers/CoreContainer';
|
|
||||||
import SocketStatusContainer from '../containers/SocketStatusContainer';
|
|
||||||
|
|
||||||
const CoreWrapper = React.memo(({ isInitializing }) => (
|
|
||||||
<>
|
|
||||||
{isInitializing ? <Loader active size="massive" /> : <CoreContainer />}
|
|
||||||
<SocketStatusContainer />
|
|
||||||
</>
|
|
||||||
));
|
|
||||||
|
|
||||||
CoreWrapper.propTypes = {
|
|
||||||
isInitializing: PropTypes.bool.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CoreWrapper;
|
|
37
client/src/components/CoreWrapper/CoreWrapper.jsx
Executable file
37
client/src/components/CoreWrapper/CoreWrapper.jsx
Executable file
|
@ -0,0 +1,37 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useTranslation, Trans } from 'react-i18next';
|
||||||
|
import { Loader } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
import CoreContainer from '../../containers/CoreContainer';
|
||||||
|
|
||||||
|
import styles from './CoreWrapper.module.scss';
|
||||||
|
|
||||||
|
const CoreWrapper = React.memo(({ isInitializing, isSocketDisconnected }) => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isInitializing ? <Loader active size="massive" /> : <CoreContainer />}
|
||||||
|
{isSocketDisconnected && (
|
||||||
|
<div className={styles.message}>
|
||||||
|
<div className={styles.messageHeader}>{t('common.noConnectionToServer')}</div>
|
||||||
|
<div className={styles.messageContent}>
|
||||||
|
<Trans i18nKey="common.allChangesWillBeAutomaticallySavedAfterConnectionRestored">
|
||||||
|
All changes will be automatically saved
|
||||||
|
<br />
|
||||||
|
after connection restored
|
||||||
|
</Trans>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
CoreWrapper.propTypes = {
|
||||||
|
isInitializing: PropTypes.bool.isRequired,
|
||||||
|
isSocketDisconnected: PropTypes.bool.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CoreWrapper;
|
|
@ -1,29 +1,5 @@
|
||||||
:global(#app) {
|
:global(#app) {
|
||||||
.button {
|
.message {
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
color: #fff;
|
|
||||||
cursor: pointer;
|
|
||||||
outline: none;
|
|
||||||
padding: 0;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
color: #fff;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
color: #fff;
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: bold;
|
|
||||||
line-height: 1.2;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper {
|
|
||||||
background: #eb5a46;
|
background: #eb5a46;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
bottom: 20px;
|
bottom: 20px;
|
||||||
|
@ -34,4 +10,18 @@
|
||||||
width: 390px;
|
width: 390px;
|
||||||
z-index: 10001;
|
z-index: 10001;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.messageContent {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.messageHeader {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
3
client/src/components/CoreWrapper/index.js
Normal file
3
client/src/components/CoreWrapper/index.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import CoreWrapper from './CoreWrapper';
|
||||||
|
|
||||||
|
export default CoreWrapper;
|
|
@ -3,22 +3,26 @@ import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import HeaderContainer from '../../containers/HeaderContainer';
|
import HeaderContainer from '../../containers/HeaderContainer';
|
||||||
import ProjectContainer from '../../containers/ProjectContainer';
|
import ProjectContainer from '../../containers/ProjectContainer';
|
||||||
|
import BoardActionsContainer from '../../containers/BoardActionsContainer';
|
||||||
|
|
||||||
import styles from './Fixed.module.scss';
|
import styles from './Fixed.module.scss';
|
||||||
|
|
||||||
const Fixed = ({ projectId }) => (
|
const Fixed = ({ projectId, board }) => (
|
||||||
<div className={styles.wrapper}>
|
<div className={styles.wrapper}>
|
||||||
<HeaderContainer />
|
<HeaderContainer />
|
||||||
{projectId && <ProjectContainer />}
|
{projectId && <ProjectContainer />}
|
||||||
|
{board && !board.isFetching && <BoardActionsContainer />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
Fixed.propTypes = {
|
Fixed.propTypes = {
|
||||||
projectId: PropTypes.string,
|
projectId: PropTypes.string,
|
||||||
|
board: PropTypes.object, // eslint-disable-line react/forbid-prop-types
|
||||||
};
|
};
|
||||||
|
|
||||||
Fixed.defaultProps = {
|
Fixed.defaultProps = {
|
||||||
projectId: undefined,
|
projectId: undefined,
|
||||||
|
board: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Fixed;
|
export default Fixed;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import classNames from 'classnames';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Icon, Menu } from 'semantic-ui-react';
|
import { Icon, Menu } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
@ -11,52 +12,98 @@ import styles from './Header.module.scss';
|
||||||
|
|
||||||
const Header = React.memo(
|
const Header = React.memo(
|
||||||
({
|
({
|
||||||
|
project,
|
||||||
user,
|
user,
|
||||||
notifications,
|
notifications,
|
||||||
isEditable,
|
canEditProject,
|
||||||
onUsers,
|
canEditUsers,
|
||||||
|
onProjectSettingsClick,
|
||||||
|
onUsersClick,
|
||||||
onNotificationDelete,
|
onNotificationDelete,
|
||||||
onUserSettings,
|
onUserSettingsClick,
|
||||||
onLogout,
|
onLogout,
|
||||||
}) => (
|
}) => {
|
||||||
<div className={styles.wrapper}>
|
const handleProjectSettingsClick = useCallback(() => {
|
||||||
<Link to={Paths.ROOT} className={styles.logo}>
|
if (canEditProject) {
|
||||||
Planka
|
onProjectSettingsClick();
|
||||||
</Link>
|
}
|
||||||
<Menu inverted size="large" className={styles.menu}>
|
}, [canEditProject, onProjectSettingsClick]);
|
||||||
<Menu.Menu position="right">
|
|
||||||
{isEditable && (
|
return (
|
||||||
<Menu.Item className={styles.item} onClick={onUsers}>
|
<div className={styles.wrapper}>
|
||||||
<Icon fitted name="users" />
|
{!project && (
|
||||||
</Menu.Item>
|
<Link to={Paths.ROOT} className={classNames(styles.logo, styles.title)}>
|
||||||
|
Planka
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
<Menu inverted size="large" className={styles.menu}>
|
||||||
|
{project && (
|
||||||
|
<Menu.Menu position="left">
|
||||||
|
<Menu.Item
|
||||||
|
as={Link}
|
||||||
|
to={Paths.ROOT}
|
||||||
|
className={classNames(styles.item, styles.itemHoverable)}
|
||||||
|
>
|
||||||
|
<Icon fitted name="arrow left" />
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
className={classNames(
|
||||||
|
styles.item,
|
||||||
|
canEditProject && styles.itemHoverable,
|
||||||
|
styles.title,
|
||||||
|
)}
|
||||||
|
onClick={handleProjectSettingsClick}
|
||||||
|
>
|
||||||
|
{project.name}
|
||||||
|
</Menu.Item>
|
||||||
|
</Menu.Menu>
|
||||||
)}
|
)}
|
||||||
<NotificationsPopup items={notifications} onDelete={onNotificationDelete}>
|
<Menu.Menu position="right">
|
||||||
<Menu.Item className={styles.item}>
|
{canEditUsers && (
|
||||||
<Icon fitted name="bell" />
|
<Menu.Item
|
||||||
{notifications.length > 0 && (
|
className={classNames(styles.item, styles.itemHoverable)}
|
||||||
<span className={styles.notification}>{notifications.length}</span>
|
onClick={onUsersClick}
|
||||||
)}
|
>
|
||||||
</Menu.Item>
|
<Icon fitted name="users" />
|
||||||
</NotificationsPopup>
|
</Menu.Item>
|
||||||
<UserPopup onSettings={onUserSettings} onLogout={onLogout}>
|
)}
|
||||||
<Menu.Item className={styles.item}>{user.name}</Menu.Item>
|
<NotificationsPopup items={notifications} onDelete={onNotificationDelete}>
|
||||||
</UserPopup>
|
<Menu.Item className={classNames(styles.item, styles.itemHoverable)}>
|
||||||
</Menu.Menu>
|
<Icon fitted name="bell" />
|
||||||
</Menu>
|
{notifications.length > 0 && (
|
||||||
</div>
|
<span className={styles.notification}>{notifications.length}</span>
|
||||||
),
|
)}
|
||||||
|
</Menu.Item>
|
||||||
|
</NotificationsPopup>
|
||||||
|
<UserPopup onSettingsClick={onUserSettingsClick} onLogout={onLogout}>
|
||||||
|
<Menu.Item className={classNames(styles.item, styles.itemHoverable)}>
|
||||||
|
{user.name}
|
||||||
|
</Menu.Item>
|
||||||
|
</UserPopup>
|
||||||
|
</Menu.Menu>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Header.propTypes = {
|
Header.propTypes = {
|
||||||
/* eslint-disable react/forbid-prop-types */
|
/* eslint-disable react/forbid-prop-types */
|
||||||
|
project: PropTypes.object,
|
||||||
user: PropTypes.object.isRequired,
|
user: PropTypes.object.isRequired,
|
||||||
notifications: PropTypes.array.isRequired,
|
notifications: PropTypes.array.isRequired,
|
||||||
/* eslint-enable react/forbid-prop-types */
|
/* eslint-enable react/forbid-prop-types */
|
||||||
isEditable: PropTypes.bool.isRequired,
|
canEditProject: PropTypes.bool.isRequired,
|
||||||
onUsers: PropTypes.func.isRequired,
|
canEditUsers: PropTypes.bool.isRequired,
|
||||||
|
onProjectSettingsClick: PropTypes.func.isRequired,
|
||||||
|
onUsersClick: PropTypes.func.isRequired,
|
||||||
onNotificationDelete: PropTypes.func.isRequired,
|
onNotificationDelete: PropTypes.func.isRequired,
|
||||||
onUserSettings: PropTypes.func.isRequired,
|
onUserSettingsClick: PropTypes.func.isRequired,
|
||||||
onLogout: PropTypes.func.isRequired,
|
onLogout: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Header.defaultProps = {
|
||||||
|
project: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
export default Header;
|
export default Header;
|
||||||
|
|
|
@ -1,19 +1,26 @@
|
||||||
:global(#app) {
|
:global(#app) {
|
||||||
.item {
|
.item {
|
||||||
|
cursor: auto;
|
||||||
|
user-select: auto;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:active, &:hover {
|
||||||
background: rgba(0, 0, 0, 0.32);
|
background: transparent;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.itemHoverable:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background: rgba(0, 0, 0, 0.32);
|
||||||
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
font-size: 20px;
|
|
||||||
font-weight: bold;
|
|
||||||
letter-spacing: 3.5px;
|
letter-spacing: 3.5px;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
|
@ -54,6 +61,11 @@
|
||||||
width: 16px;
|
width: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
background: rgba(0, 0, 0, 0.24);
|
background: rgba(0, 0, 0, 0.24);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -65,13 +65,11 @@ const ActionsStep = React.memo(({ onNameEdit, onCardAdd, onDelete, onClose }) =>
|
||||||
context: 'title',
|
context: 'title',
|
||||||
})}
|
})}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
{onDelete && (
|
<Menu.Item className={styles.menuItem} onClick={handleDeleteClick}>
|
||||||
<Menu.Item className={styles.menuItem} onClick={handleDeleteClick}>
|
{t('action.deleteList', {
|
||||||
{t('action.deleteList', {
|
context: 'title',
|
||||||
context: 'title',
|
})}
|
||||||
})}
|
</Menu.Item>
|
||||||
</Menu.Item>
|
|
||||||
)}
|
|
||||||
</Menu>
|
</Menu>
|
||||||
</Popup.Content>
|
</Popup.Content>
|
||||||
</>
|
</>
|
||||||
|
@ -81,12 +79,8 @@ const ActionsStep = React.memo(({ onNameEdit, onCardAdd, onDelete, onClose }) =>
|
||||||
ActionsStep.propTypes = {
|
ActionsStep.propTypes = {
|
||||||
onNameEdit: PropTypes.func.isRequired,
|
onNameEdit: PropTypes.func.isRequired,
|
||||||
onCardAdd: PropTypes.func.isRequired,
|
onCardAdd: PropTypes.func.isRequired,
|
||||||
onDelete: PropTypes.func,
|
onDelete: PropTypes.func.isRequired,
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
ActionsStep.defaultProps = {
|
|
||||||
onDelete: undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default withPopup(ActionsStep);
|
export default withPopup(ActionsStep);
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { ReactComponent as PlusMathIcon } from '../../assets/images/plus-math-ic
|
||||||
import styles from './List.module.scss';
|
import styles from './List.module.scss';
|
||||||
|
|
||||||
const List = React.memo(
|
const List = React.memo(
|
||||||
({ id, index, name, isPersisted, cardIds, onUpdate, onDelete, onCardCreate }) => {
|
({ id, index, name, isPersisted, cardIds, canEdit, onUpdate, onDelete, onCardCreate }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const [isAddCardOpened, setIsAddCardOpened] = useState(false);
|
const [isAddCardOpened, setIsAddCardOpened] = useState(false);
|
||||||
|
|
||||||
|
@ -23,10 +23,10 @@ const List = React.memo(
|
||||||
const listWrapper = useRef(null);
|
const listWrapper = useRef(null);
|
||||||
|
|
||||||
const handleHeaderClick = useCallback(() => {
|
const handleHeaderClick = useCallback(() => {
|
||||||
if (isPersisted) {
|
if (isPersisted && canEdit) {
|
||||||
nameEdit.current.open();
|
nameEdit.current.open();
|
||||||
}
|
}
|
||||||
}, [isPersisted]);
|
}, [isPersisted, canEdit]);
|
||||||
|
|
||||||
const handleNameUpdate = useCallback(
|
const handleNameUpdate = useCallback(
|
||||||
(newName) => {
|
(newName) => {
|
||||||
|
@ -73,11 +73,13 @@ const List = React.memo(
|
||||||
<CardContainer key={cardId} id={cardId} index={cardIndex} />
|
<CardContainer key={cardId} id={cardId} index={cardIndex} />
|
||||||
))}
|
))}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
<CardAdd
|
{canEdit && (
|
||||||
isOpened={isAddCardOpened}
|
<CardAdd
|
||||||
onCreate={onCardCreate}
|
isOpened={isAddCardOpened}
|
||||||
onClose={handleAddCardClose}
|
onCreate={onCardCreate}
|
||||||
/>
|
onClose={handleAddCardClose}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -85,51 +87,64 @@ const List = React.memo(
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Draggable draggableId={`list:${id}`} index={index} isDragDisabled={!isPersisted}>
|
<Draggable draggableId={`list:${id}`} index={index} isDragDisabled={!isPersisted || !canEdit}>
|
||||||
{({ innerRef, draggableProps, dragHandleProps }) => (
|
{({ innerRef, draggableProps, dragHandleProps }) => (
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
<div
|
||||||
<div {...draggableProps} data-drag-scroller ref={innerRef} className={styles.wrapper}>
|
{...draggableProps} // eslint-disable-line react/jsx-props-no-spreading
|
||||||
|
data-drag-scroller
|
||||||
|
ref={innerRef}
|
||||||
|
className={styles.innerWrapper}
|
||||||
|
>
|
||||||
{/* eslint-disable jsx-a11y/click-events-have-key-events,
|
{/* eslint-disable jsx-a11y/click-events-have-key-events,
|
||||||
jsx-a11y/no-static-element-interactions,
|
jsx-a11y/no-static-element-interactions,
|
||||||
react/jsx-props-no-spreading */}
|
react/jsx-props-no-spreading */}
|
||||||
<div {...dragHandleProps} className={styles.header} onClick={handleHeaderClick}>
|
<div className={styles.outerWrapper}>
|
||||||
{/* eslint-enable jsx-a11y/click-events-have-key-events,
|
<div
|
||||||
|
{...dragHandleProps}
|
||||||
|
className={classNames(styles.header, canEdit && styles.headerEditable)}
|
||||||
|
onClick={handleHeaderClick}
|
||||||
|
>
|
||||||
|
{/* eslint-enable jsx-a11y/click-events-have-key-events,
|
||||||
jsx-a11y/no-static-element-interactions,
|
jsx-a11y/no-static-element-interactions,
|
||||||
react/jsx-props-no-spreading */}
|
react/jsx-props-no-spreading */}
|
||||||
<NameEdit ref={nameEdit} defaultValue={name} onUpdate={handleNameUpdate}>
|
<NameEdit ref={nameEdit} defaultValue={name} onUpdate={handleNameUpdate}>
|
||||||
<div className={styles.headerName}>{name}</div>
|
<div className={styles.headerName}>{name}</div>
|
||||||
</NameEdit>
|
</NameEdit>
|
||||||
{isPersisted && (
|
{isPersisted && canEdit && (
|
||||||
<ActionsPopup
|
<ActionsPopup
|
||||||
onNameEdit={handleNameEdit}
|
onNameEdit={handleNameEdit}
|
||||||
onCardAdd={handleCardAdd}
|
onCardAdd={handleCardAdd}
|
||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
|
>
|
||||||
|
<Button className={classNames(styles.headerButton, styles.target)}>
|
||||||
|
<Icon fitted name="pencil" size="small" />
|
||||||
|
</Button>
|
||||||
|
</ActionsPopup>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
ref={listWrapper}
|
||||||
|
className={classNames(
|
||||||
|
styles.cardsInnerWrapper,
|
||||||
|
(isAddCardOpened || !canEdit) && styles.cardsInnerWrapperFull,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className={styles.cardsOuterWrapper}>{cardsNode}</div>
|
||||||
|
</div>
|
||||||
|
{!isAddCardOpened && canEdit && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
disabled={!isPersisted}
|
||||||
|
className={classNames(styles.addCardButton)}
|
||||||
|
onClick={handleAddCardClick}
|
||||||
>
|
>
|
||||||
<Button className={classNames(styles.headerButton, styles.target)}>
|
<PlusMathIcon className={styles.addCardButtonIcon} />
|
||||||
<Icon fitted name="pencil" size="small" />
|
<span className={styles.addCardButtonText}>
|
||||||
</Button>
|
{cardIds.length > 0 ? t('action.addAnotherCard') : t('action.addCard')}
|
||||||
</ActionsPopup>
|
</span>
|
||||||
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
ref={listWrapper}
|
|
||||||
className={classNames(styles.listWrapper, isAddCardOpened && styles.listWrapperFull)}
|
|
||||||
>
|
|
||||||
<div className={styles.list}>{cardsNode}</div>
|
|
||||||
</div>
|
|
||||||
{!isAddCardOpened && (
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
disabled={!isPersisted}
|
|
||||||
className={styles.addCardButton}
|
|
||||||
onClick={handleAddCardClick}
|
|
||||||
>
|
|
||||||
<PlusMathIcon className={styles.addCardButtonIcon} />
|
|
||||||
<span className={styles.addCardButtonText}>
|
|
||||||
{cardIds.length > 0 ? t('action.addAnotherCard') : t('action.addCard')}
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Draggable>
|
</Draggable>
|
||||||
|
@ -143,13 +158,10 @@ List.propTypes = {
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
isPersisted: PropTypes.bool.isRequired,
|
isPersisted: PropTypes.bool.isRequired,
|
||||||
cardIds: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
cardIds: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
|
canEdit: PropTypes.bool.isRequired,
|
||||||
onUpdate: PropTypes.func.isRequired,
|
onUpdate: PropTypes.func.isRequired,
|
||||||
onDelete: PropTypes.func,
|
onDelete: PropTypes.func.isRequired,
|
||||||
onCardCreate: PropTypes.func.isRequired,
|
onCardCreate: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
List.defaultProps = {
|
|
||||||
onDelete: undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default List;
|
export default List;
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
.addCardButton {
|
.addCardButton {
|
||||||
background: #dfe3e6;
|
background: #dfe3e6;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 0 0 3px 3px;
|
|
||||||
color: #6b808c;
|
color: #6b808c;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -37,76 +36,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.cards {
|
.cards {
|
||||||
flex: 1 1 auto;
|
|
||||||
min-height: 1px;
|
min-height: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.cardsInnerWrapper {
|
||||||
background: #dfe3e6;
|
max-height: calc(100vh - 268px);
|
||||||
border-radius: 3px 3px 0 0;
|
|
||||||
box-sizing: none;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
margin-bottom: 0;
|
|
||||||
outline: none;
|
|
||||||
padding: 6px 36px 4px 8px;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&:hover .target {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerButton {
|
|
||||||
background: none;
|
|
||||||
box-shadow: none;
|
|
||||||
color: #798d99;
|
|
||||||
line-height: 32px;
|
|
||||||
margin: 0;
|
|
||||||
opacity: 0;
|
|
||||||
padding: 0;
|
|
||||||
position: absolute;
|
|
||||||
right: 2px;
|
|
||||||
top: 2px;
|
|
||||||
width: 32px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: rgba(9, 30, 66, 0.13);
|
|
||||||
color: #516b7a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerName {
|
|
||||||
background: transparent;
|
|
||||||
border-color: transparent;
|
|
||||||
border-radius: 3px;
|
|
||||||
color: #17394d;
|
|
||||||
font-weight: bold;
|
|
||||||
line-height: 20px;
|
|
||||||
margin: 0;
|
|
||||||
max-height: 256px;
|
|
||||||
outline: none;
|
|
||||||
overflow: hidden;
|
|
||||||
overflow-wrap: break-word;
|
|
||||||
padding: 4px 8px;
|
|
||||||
resize: none;
|
|
||||||
width: 100%;
|
|
||||||
word-break: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list {
|
|
||||||
background: #dfe3e6;
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 0 8px;
|
|
||||||
position: relative;
|
|
||||||
white-space: normal;
|
|
||||||
width: 272px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.listWrapper {
|
|
||||||
background: #dfe3e6;
|
|
||||||
max-height: calc(100vh - 300px);
|
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
|
@ -129,16 +63,69 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.listWrapperFull {
|
.cardsInnerWrapperFull {
|
||||||
max-height: calc(100vh - 264px);
|
max-height: calc(100vh - 232px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.cardsOuterWrapper {
|
||||||
border-radius: 3px;
|
padding: 0 8px;
|
||||||
flex: 0 0 auto;
|
white-space: normal;
|
||||||
margin: 0 4px;
|
|
||||||
overflow: hidden;
|
|
||||||
vertical-align: top;
|
|
||||||
width: 272px;
|
width: 272px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
outline: none;
|
||||||
|
padding: 6px 36px 4px 8px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover .target {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerEditable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerButton {
|
||||||
|
background: none;
|
||||||
|
box-shadow: none;
|
||||||
|
color: #798d99;
|
||||||
|
line-height: 32px;
|
||||||
|
margin: 0;
|
||||||
|
opacity: 0;
|
||||||
|
padding: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 2px;
|
||||||
|
top: 2px;
|
||||||
|
width: 32px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(9, 30, 66, 0.13);
|
||||||
|
color: #516b7a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerName {
|
||||||
|
color: #17394d;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 20px;
|
||||||
|
max-height: 256px;
|
||||||
|
outline: none;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
padding: 4px 8px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.innerWrapper {
|
||||||
|
margin-right: 8px;
|
||||||
|
width: 272px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.outerWrapper {
|
||||||
|
background: #dfe3e6;
|
||||||
|
border-radius: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
110
client/src/components/Memberships/ActionsPopup.jsx
Executable file
110
client/src/components/Memberships/ActionsPopup.jsx
Executable file
|
@ -0,0 +1,110 @@
|
||||||
|
import React, { useCallback } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Button } from 'semantic-ui-react';
|
||||||
|
import { withPopup } from '../../lib/popup';
|
||||||
|
|
||||||
|
import { useSteps } from '../../hooks';
|
||||||
|
import User from '../User';
|
||||||
|
import DeleteStep from '../DeleteStep';
|
||||||
|
|
||||||
|
import styles from './ActionsPopup.module.scss';
|
||||||
|
|
||||||
|
const StepTypes = {
|
||||||
|
DELETE: 'DELETE',
|
||||||
|
};
|
||||||
|
|
||||||
|
const ActionsStep = React.memo(
|
||||||
|
({
|
||||||
|
user,
|
||||||
|
leaveButtonContent,
|
||||||
|
leaveConfirmationTitle,
|
||||||
|
leaveConfirmationContent,
|
||||||
|
leaveConfirmationButtonContent,
|
||||||
|
deleteButtonContent,
|
||||||
|
deleteConfirmationTitle,
|
||||||
|
deleteConfirmationContent,
|
||||||
|
deleteConfirmationButtonContent,
|
||||||
|
canLeave,
|
||||||
|
canDelete,
|
||||||
|
onDelete,
|
||||||
|
}) => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
const [step, openStep, handleBack] = useSteps();
|
||||||
|
|
||||||
|
const handleDeleteClick = useCallback(() => {
|
||||||
|
openStep(StepTypes.DELETE);
|
||||||
|
}, [openStep]);
|
||||||
|
|
||||||
|
if (step && step.type === StepTypes.DELETE) {
|
||||||
|
return (
|
||||||
|
<DeleteStep
|
||||||
|
title={t(user.isCurrent ? leaveConfirmationTitle : deleteConfirmationTitle, {
|
||||||
|
context: 'title',
|
||||||
|
})}
|
||||||
|
content={t(user.isCurrent ? leaveConfirmationContent : deleteConfirmationContent)}
|
||||||
|
buttonContent={t(
|
||||||
|
user.isCurrent ? leaveConfirmationButtonContent : deleteConfirmationButtonContent,
|
||||||
|
)}
|
||||||
|
onConfirm={onDelete}
|
||||||
|
onBack={handleBack}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<span className={styles.user}>
|
||||||
|
<User name={user.name} avatarUrl={user.avatarUrl} size="large" />
|
||||||
|
</span>
|
||||||
|
<span className={styles.content}>
|
||||||
|
<div className={styles.name}>{user.name}</div>
|
||||||
|
<div className={styles.email}>{user.email}</div>
|
||||||
|
{user.isCurrent
|
||||||
|
? canLeave && (
|
||||||
|
<Button
|
||||||
|
content={t(leaveButtonContent)}
|
||||||
|
className={styles.deleteButton}
|
||||||
|
onClick={handleDeleteClick}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: canDelete && (
|
||||||
|
<Button
|
||||||
|
content={t(deleteButtonContent)}
|
||||||
|
className={styles.deleteButton}
|
||||||
|
onClick={handleDeleteClick}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ActionsStep.propTypes = {
|
||||||
|
user: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
|
leaveButtonContent: PropTypes.string,
|
||||||
|
leaveConfirmationTitle: PropTypes.string,
|
||||||
|
leaveConfirmationContent: PropTypes.string,
|
||||||
|
leaveConfirmationButtonContent: PropTypes.string,
|
||||||
|
deleteButtonContent: PropTypes.string,
|
||||||
|
deleteConfirmationTitle: PropTypes.string,
|
||||||
|
deleteConfirmationContent: PropTypes.string,
|
||||||
|
deleteConfirmationButtonContent: PropTypes.string,
|
||||||
|
canLeave: PropTypes.bool.isRequired,
|
||||||
|
canDelete: PropTypes.bool.isRequired,
|
||||||
|
onDelete: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
ActionsStep.defaultProps = {
|
||||||
|
leaveButtonContent: 'action.leaveBoard',
|
||||||
|
leaveConfirmationTitle: 'common.leaveBoard',
|
||||||
|
leaveConfirmationContent: 'common.areYouSureYouWantToLeaveBoard',
|
||||||
|
leaveConfirmationButtonContent: 'action.leaveBoard',
|
||||||
|
deleteButtonContent: 'action.removeFromBoard',
|
||||||
|
deleteConfirmationTitle: 'common.removeMember',
|
||||||
|
deleteConfirmationContent: 'common.areYouSureYouWantToRemoveThisMemberFromBoard',
|
||||||
|
deleteConfirmationButtonContent: 'action.removeMember',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withPopup(ActionsStep);
|
|
@ -6,9 +6,9 @@ import { Popup } from '../../../lib/custom-ui';
|
||||||
|
|
||||||
import UserItem from './UserItem';
|
import UserItem from './UserItem';
|
||||||
|
|
||||||
import styles from './MembershipAddPopup.module.scss';
|
import styles from './AddPopup.module.scss';
|
||||||
|
|
||||||
const MembershipAddStep = React.memo(({ users, currentUserIds, onCreate, onClose }) => {
|
const AddStep = React.memo(({ users, currentUserIds, title, onCreate, onClose }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
const handleUserSelect = useCallback(
|
const handleUserSelect = useCallback(
|
||||||
|
@ -25,7 +25,7 @@ const MembershipAddStep = React.memo(({ users, currentUserIds, onCreate, onClose
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Popup.Header>
|
<Popup.Header>
|
||||||
{t('common.addMember', {
|
{t(title, {
|
||||||
context: 'title',
|
context: 'title',
|
||||||
})}
|
})}
|
||||||
</Popup.Header>
|
</Popup.Header>
|
||||||
|
@ -46,13 +46,18 @@ const MembershipAddStep = React.memo(({ users, currentUserIds, onCreate, onClose
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
MembershipAddStep.propTypes = {
|
AddStep.propTypes = {
|
||||||
/* eslint-disable react/forbid-prop-types */
|
/* eslint-disable react/forbid-prop-types */
|
||||||
users: PropTypes.array.isRequired,
|
users: PropTypes.array.isRequired,
|
||||||
currentUserIds: PropTypes.array.isRequired,
|
currentUserIds: PropTypes.array.isRequired,
|
||||||
/* eslint-disable react/forbid-prop-types */
|
/* eslint-disable react/forbid-prop-types */
|
||||||
|
title: PropTypes.string,
|
||||||
onCreate: PropTypes.func.isRequired,
|
onCreate: PropTypes.func.isRequired,
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(MembershipAddStep);
|
AddStep.defaultProps = {
|
||||||
|
title: 'common.addMember',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withPopup(AddStep);
|
3
client/src/components/Memberships/AddPopup/index.js
Normal file
3
client/src/components/Memberships/AddPopup/index.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import AddPopup from './AddPopup';
|
||||||
|
|
||||||
|
export default AddPopup;
|
107
client/src/components/Memberships/Memberships.jsx
Normal file
107
client/src/components/Memberships/Memberships.jsx
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Button } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
import AddPopup from './AddPopup';
|
||||||
|
import ActionsPopup from './ActionsPopup';
|
||||||
|
import User from '../User';
|
||||||
|
|
||||||
|
import styles from './Memberships.module.scss';
|
||||||
|
|
||||||
|
const Memberships = React.memo(
|
||||||
|
({
|
||||||
|
items,
|
||||||
|
allUsers,
|
||||||
|
addTitle,
|
||||||
|
leaveButtonContent,
|
||||||
|
leaveConfirmationTitle,
|
||||||
|
leaveConfirmationContent,
|
||||||
|
leaveConfirmationButtonContent,
|
||||||
|
deleteButtonContent,
|
||||||
|
deleteConfirmationTitle,
|
||||||
|
deleteConfirmationContent,
|
||||||
|
deleteConfirmationButtonContent,
|
||||||
|
canEdit,
|
||||||
|
canLeaveIfLast,
|
||||||
|
onCreate,
|
||||||
|
onDelete,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<span className={styles.users}>
|
||||||
|
{items.map((item) => (
|
||||||
|
<span key={item.id} className={styles.user}>
|
||||||
|
<ActionsPopup
|
||||||
|
user={item.user}
|
||||||
|
leaveButtonContent={leaveButtonContent}
|
||||||
|
leaveConfirmationTitle={leaveConfirmationTitle}
|
||||||
|
leaveConfirmationContent={leaveConfirmationContent}
|
||||||
|
leaveConfirmationButtonContent={leaveConfirmationButtonContent}
|
||||||
|
deleteButtonContent={deleteButtonContent}
|
||||||
|
deleteConfirmationTitle={deleteConfirmationTitle}
|
||||||
|
deleteConfirmationContent={deleteConfirmationContent}
|
||||||
|
deleteConfirmationButtonContent={deleteConfirmationButtonContent}
|
||||||
|
canLeave={items.length > 1 || canLeaveIfLast}
|
||||||
|
canDelete={canEdit}
|
||||||
|
onDelete={() => onDelete(item.id)}
|
||||||
|
>
|
||||||
|
<User
|
||||||
|
name={item.user.name}
|
||||||
|
avatarUrl={item.user.avatarUrl}
|
||||||
|
size="large"
|
||||||
|
isDisabled={!item.isPersisted}
|
||||||
|
/>
|
||||||
|
</ActionsPopup>
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</span>
|
||||||
|
{canEdit && (
|
||||||
|
<AddPopup
|
||||||
|
users={allUsers}
|
||||||
|
currentUserIds={items.map((item) => item.user.id)}
|
||||||
|
title={addTitle}
|
||||||
|
onCreate={onCreate}
|
||||||
|
>
|
||||||
|
<Button icon="add user" className={styles.addUser} />
|
||||||
|
</AddPopup>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Memberships.propTypes = {
|
||||||
|
/* eslint-disable react/forbid-prop-types */
|
||||||
|
items: PropTypes.array.isRequired,
|
||||||
|
allUsers: PropTypes.array.isRequired,
|
||||||
|
/* eslint-enable react/forbid-prop-types */
|
||||||
|
addTitle: PropTypes.string,
|
||||||
|
leaveButtonContent: PropTypes.string,
|
||||||
|
leaveConfirmationTitle: PropTypes.string,
|
||||||
|
leaveConfirmationContent: PropTypes.string,
|
||||||
|
leaveConfirmationButtonContent: PropTypes.string,
|
||||||
|
deleteButtonContent: PropTypes.string,
|
||||||
|
deleteConfirmationTitle: PropTypes.string,
|
||||||
|
deleteConfirmationContent: PropTypes.string,
|
||||||
|
deleteConfirmationButtonContent: PropTypes.string,
|
||||||
|
canEdit: PropTypes.bool,
|
||||||
|
canLeaveIfLast: PropTypes.bool,
|
||||||
|
onCreate: PropTypes.func.isRequired,
|
||||||
|
onDelete: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
Memberships.defaultProps = {
|
||||||
|
addTitle: undefined,
|
||||||
|
leaveButtonContent: undefined,
|
||||||
|
leaveConfirmationTitle: undefined,
|
||||||
|
leaveConfirmationContent: undefined,
|
||||||
|
leaveConfirmationButtonContent: undefined,
|
||||||
|
deleteButtonContent: undefined,
|
||||||
|
deleteConfirmationTitle: undefined,
|
||||||
|
deleteConfirmationContent: undefined,
|
||||||
|
deleteConfirmationButtonContent: undefined,
|
||||||
|
canEdit: true,
|
||||||
|
canLeaveIfLast: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Memberships;
|
30
client/src/components/Memberships/Memberships.module.scss
Normal file
30
client/src/components/Memberships/Memberships.module.scss
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
:global(#app) {
|
||||||
|
.addUser {
|
||||||
|
background: rgba(0, 0, 0, 0.24);
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: none;
|
||||||
|
color: #fff;
|
||||||
|
line-height: 36px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
transition: all 0.1s ease 0s;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 36px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 -4px 0 0;
|
||||||
|
vertical-align: top;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.users {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
}
|
3
client/src/components/Memberships/index.js
Normal file
3
client/src/components/Memberships/index.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import Memberships from './Memberships';
|
||||||
|
|
||||||
|
export default Memberships;
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue