Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
513f9a8ee5 | ||
|
|
e051f624a8 | ||
|
|
172f4fcf34 | ||
|
|
9f16881965 | ||
|
|
4e876922f8 | ||
|
|
d82d928e29 | ||
|
|
94dc83706c | ||
|
|
b08e731419 | ||
|
|
1ce0fac281 | ||
|
|
e3d00c8791 | ||
|
|
e1a0b635ea | ||
|
|
cc7959bb15 | ||
|
|
56044e6d8a | ||
|
|
e5bd73f33e | ||
|
|
e65ab6ece7 | ||
|
|
14cc55a8c0 | ||
|
|
b4306d0a4b | ||
|
|
283c850ebf | ||
|
|
62de71bd97 | ||
|
|
447f88880d | ||
|
|
8109936ce2 | ||
|
|
640908320a | ||
|
|
236c1020b3 | ||
|
|
3df07c10fa | ||
|
|
543a992d98 | ||
|
|
9cde4e63f9 | ||
|
|
95738ee7d3 | ||
|
|
bb7cdf5dd4 | ||
|
|
253af55790 | ||
|
|
62c3cca9a7 | ||
|
|
b476a19b79 | ||
|
|
3379c65a87 | ||
|
|
1a6fc40804 | ||
|
|
42092efcd2 | ||
|
|
5c91bddfe7 | ||
|
|
fd8f40f1b0 | ||
|
|
5b64d465e2 | ||
|
|
212fb8ac8c | ||
|
|
cece2254d7 | ||
|
|
c940805f14 | ||
|
|
052ab7f653 | ||
|
|
5a38805588 | ||
|
|
2dbbead2e9 | ||
|
|
039eee0aac | ||
|
|
07867fc0b2 | ||
|
|
55d07b4560 | ||
|
|
289d2bf5ae | ||
|
|
6429e22d59 | ||
|
|
21ef850913 | ||
|
|
e4769220da | ||
|
|
378e02c0a4 | ||
|
|
51fa7df69c | ||
|
|
68806b9080 | ||
|
|
d80a538857 | ||
|
|
78669da01d | ||
|
|
3a7720974b | ||
|
|
eea94e0ee2 | ||
|
|
4555dafd75 | ||
|
|
95ebb27042 | ||
|
|
d38e555293 | ||
|
|
7786533a90 | ||
|
|
dab38cbc18 | ||
|
|
3714bbc06f | ||
|
|
1f569bdb61 | ||
|
|
ac1df5201d | ||
|
|
fbe24c0fc0 | ||
|
|
79daed6afa | ||
|
|
a9111bf7ba | ||
|
|
2d50211892 | ||
|
|
139971eca9 | ||
|
|
34db8947b6 | ||
|
|
82e4f73c1f | ||
|
|
560bddbe18 | ||
|
|
9c192f4b5c | ||
|
|
a148a3aae5 | ||
|
|
7c1b885d2a | ||
|
|
a3f33d0361 | ||
|
|
fe62180cda | ||
|
|
58abd0691f | ||
|
|
ad67b9ba24 | ||
|
|
ddf9a32ea9 | ||
|
|
e01a2eafba | ||
|
|
3b3bff1b6b | ||
|
|
ecc45c7a9e |
@@ -7,4 +7,5 @@
|
|||||||
|
|
||||||
server/public/*
|
server/public/*
|
||||||
server/views/*
|
server/views/*
|
||||||
|
server/logs
|
||||||
client/build
|
client/build
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: meltyshev
|
||||||
|
patreon: # Replace with a single Patreon username
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
liberapay: # Replace with a single Liberapay username
|
||||||
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
|
otechie: # Replace with a single Otechie username
|
||||||
|
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||||
|
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||||
@@ -2,5 +2,4 @@ node_modules
|
|||||||
docker-compose.override.yml
|
docker-compose.override.yml
|
||||||
|
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"dbaeumer.vscode-eslint"
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+18
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"editor.tabSize": 2,
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"files.insertFinalNewline": true,
|
||||||
|
"files.trimFinalNewlines": true,
|
||||||
|
"files.trimTrailingWhitespace": true,
|
||||||
|
"eslint.format.enable": true,
|
||||||
|
"eslint.workingDirectories": [
|
||||||
|
"./client",
|
||||||
|
"./server"
|
||||||
|
],
|
||||||
|
"[javascript]": {
|
||||||
|
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
||||||
|
},
|
||||||
|
"[javascriptreact]": {
|
||||||
|
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -26,7 +26,7 @@ COPY server .
|
|||||||
RUN cp .env.sample .env
|
RUN cp .env.sample .env
|
||||||
|
|
||||||
COPY --from=client-builder /app/build public
|
COPY --from=client-builder /app/build public
|
||||||
COPY --from=client-builder /app/build/index.html views
|
COPY --from=client-builder /app/build/index.html views/index.ejs
|
||||||
|
|
||||||
VOLUME /app/public/user-avatars
|
VOLUME /app/public/user-avatars
|
||||||
VOLUME /app/public/project-background-images
|
VOLUME /app/public/project-background-images
|
||||||
|
|||||||
@@ -44,6 +44,79 @@ docker-compose up -d
|
|||||||
|
|
||||||
Demo user: demo@demo.demo demo
|
Demo user: demo@demo.demo demo
|
||||||
|
|
||||||
|
### Logging
|
||||||
|
|
||||||
|
Planka currently allows you to expose the applciation's logfile directory to the host machine via a shared volume. This feature is not enabled by default.
|
||||||
|
|
||||||
|
To expose the logfile director to the host machine, add the item `./logs/:/app/logs/` under `services.planka.volumes`.
|
||||||
|
|
||||||
|
Note that the directory to the left of the semicolon is regarding the host machine while the directory to the right of the semicolon is regarding the Docker container.
|
||||||
|
|
||||||
|
For example, in the above step, `./logs/:/app/logs/` will create the folder `logs` in the same directory where the `docker-compose.yml` file lives.
|
||||||
|
|
||||||
|
### Rotating Logs
|
||||||
|
|
||||||
|
Logrotate is designed to ease administration of systems that generate large numbers of log files. It allows automatic rotation, compression, removal, and mailing of log files. Each log file may be handled daily, weekly, monthly, or when it grows too large.
|
||||||
|
|
||||||
|
#### Setup logrotate for Planka logs
|
||||||
|
|
||||||
|
Create a file in `/etc/logrotate.d` named `planka` with the following contents:
|
||||||
|
|
||||||
|
```
|
||||||
|
/path/to/planka/logs/planka.log {
|
||||||
|
daily
|
||||||
|
missingok
|
||||||
|
rotate 14
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
notifempty
|
||||||
|
create 640 root adm
|
||||||
|
sharedscripts
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Ensure to replace logfile directory with your installation’s `/logs/planka.log` location.
|
||||||
|
|
||||||
|
Restart the logrotate service.
|
||||||
|
|
||||||
|
### Fail2ban
|
||||||
|
|
||||||
|
Fail2ban is a service that uses iptables to automatically drop connections for a pre-defined amount of time from IPs that continuously failed to authenticate to the configured services.
|
||||||
|
|
||||||
|
#### Setup a filter and a jail for Planka
|
||||||
|
|
||||||
|
A filter defines regex rules to identify when users fail to authenticate on Planka's user interface.
|
||||||
|
|
||||||
|
Create a file in `/etc/fail2ban/filter.d` named `planka.conf` with the following contents:
|
||||||
|
|
||||||
|
```conf
|
||||||
|
[Definition]
|
||||||
|
failregex = ^(.*) Invalid (email or username:|password!) (\"(.*)\"!)? ?\(IP: <ADDR>\)$
|
||||||
|
ignoreregex =
|
||||||
|
```
|
||||||
|
|
||||||
|
The jail file defines how to handle the failed authentication attempts found by the Planka filter.
|
||||||
|
|
||||||
|
Create a file in `/etc/fail2ban/jail.d` named `planka.local` with the following contents:
|
||||||
|
|
||||||
|
```conf
|
||||||
|
[planka]
|
||||||
|
enabled = true
|
||||||
|
port = http,https
|
||||||
|
filter = planka
|
||||||
|
logpath = /path/to/planka/logs/planka.log
|
||||||
|
maxretry = 5
|
||||||
|
bantime = 900
|
||||||
|
```
|
||||||
|
|
||||||
|
Ensure to replace `logpath`'s value with your installation’s `/logs/planka.log` location. If you are using ports other than 80 and 443 for your Web server you should replace those too. The bantime and findtime are defined in seconds.
|
||||||
|
|
||||||
|
Restart the fail2ban service. You can check the status of your Planka jail by running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fail2ban-client status planka
|
||||||
|
```
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
Clone the repository and install dependencies:
|
Clone the repository and install dependencies:
|
||||||
|
|||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
Most recent release.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
Please report any security issues you discovered to meltyshev@gmail.com. If the issue is confirmed, we will release a patch as soon as possible depending on complexity.
|
||||||
|
|
||||||
|
**Do NOT create public issues on GitHub for security vulnerabilities.**
|
||||||
|
|
||||||
|
Thank you for your contribution!
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const BASE_URL_PLACEHOLDER = 'BASE_URL_PLACEHOLDER';
|
||||||
|
|
||||||
|
const replaceInFile = (file, search, replace) => {
|
||||||
|
fs.readFile(file, 'utf8', (readError, data) => {
|
||||||
|
if (readError) {
|
||||||
|
throw new Error(`${readError}`);
|
||||||
|
}
|
||||||
|
const res = data.replaceAll(search, replace);
|
||||||
|
fs.writeFile(file, res, 'utf8', (writeError) => {
|
||||||
|
if (writeError) {
|
||||||
|
throw new Error(`${writeError}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const replaceBaseUrl = (compiler) => {
|
||||||
|
compiler.hooks.assetEmitted.tap('ReplaceBaseUrlPlaceholder', (file, info) => {
|
||||||
|
if (info.content.indexOf(BASE_URL_PLACEHOLDER) >= 0) {
|
||||||
|
if (/\.css$/.exec(info.targetPath)) {
|
||||||
|
// For CSS 'url(...)' import we can use relative import
|
||||||
|
const relPath = path.relative(path.dirname(info.targetPath), info.outputPath);
|
||||||
|
replaceInFile(info.targetPath, BASE_URL_PLACEHOLDER, `${relPath}/`);
|
||||||
|
} else if (/\.js$/.exec(info.targetPath)) {
|
||||||
|
// For JS 'import ... from "some-asset"' we can get the variable injected in the window object
|
||||||
|
// eslint-disable-next-line no-template-curly-in-string
|
||||||
|
replaceInFile(info.targetPath, `"${BASE_URL_PLACEHOLDER}"`, '`${window.BASE_URL}/`');
|
||||||
|
} else if (/index\.html$/.exec(info.targetPath)) {
|
||||||
|
// For the main html file, we set a placeholder for sails to inject the correct value as runtime
|
||||||
|
replaceInFile(info.targetPath, BASE_URL_PLACEHOLDER, '<%= BASE_URL %>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = function override(config, env) {
|
||||||
|
if (env === 'production') {
|
||||||
|
const plugins = config.plugins.map((plugin) => {
|
||||||
|
if (plugin.constructor.name === 'InterpolateHtmlPlugin') {
|
||||||
|
const newPlugin = plugin;
|
||||||
|
newPlugin.replacements.PUBLIC_URL = BASE_URL_PLACEHOLDER;
|
||||||
|
return newPlugin;
|
||||||
|
}
|
||||||
|
return plugin;
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
output: { ...config.output, publicPath: BASE_URL_PLACEHOLDER },
|
||||||
|
plugins: [...plugins, { apply: replaceBaseUrl }],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
};
|
||||||
Generated
+9811
-6159
File diff suppressed because it is too large
Load Diff
+31
-27
@@ -2,11 +2,11 @@
|
|||||||
"name": "planka-client",
|
"name": "planka-client",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "react-scripts build",
|
"build": "react-app-rewired build",
|
||||||
"eject": "react-scripts eject",
|
"eject": "react-scripts eject",
|
||||||
"lint": "eslint --ext js,jsx src",
|
"lint": "eslint --ext js,jsx src config-overrides.js",
|
||||||
"start": "react-scripts start",
|
"start": "react-app-rewired start",
|
||||||
"test": "react-scripts test"
|
"test": "react-app-rewired test"
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
@@ -63,60 +63,64 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"classnames": "^2.2.6",
|
"@juggle/resize-observer": "^3.4.0",
|
||||||
"connected-react-router": "^6.9.2",
|
"classnames": "^2.3.1",
|
||||||
"date-fns": "^2.28.0",
|
"connected-react-router": "^6.9.3",
|
||||||
"dequal": "^2.0.2",
|
"date-fns": "^2.29.1",
|
||||||
|
"dequal": "^2.0.3",
|
||||||
"history": "^4.10.1",
|
"history": "^4.10.1",
|
||||||
"i18next": "^21.6.16",
|
"i18next": "^21.8.14",
|
||||||
"i18next-browser-languagedetector": "^6.1.4",
|
"i18next-browser-languagedetector": "^6.1.4",
|
||||||
"initials": "^3.1.2",
|
"initials": "^3.1.2",
|
||||||
"js-cookie": "^3.0.1",
|
"js-cookie": "^3.0.1",
|
||||||
"lodash": "^4.17.20",
|
"jwt-decode": "^3.1.2",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
"node-sass": "^7.0.1",
|
"node-sass": "^7.0.1",
|
||||||
"photoswipe": "^5.2.7",
|
"photoswipe": "^5.3.0",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-beautiful-dnd": "^13.0.0",
|
"react-beautiful-dnd": "^13.1.0",
|
||||||
"react-datepicker": "^4.7.0",
|
"react-datepicker": "^4.8.0",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-dropzone": "^12.0.5",
|
"react-dropzone": "^14.2.2",
|
||||||
"react-i18next": "^11.16.6",
|
"react-i18next": "^11.18.1",
|
||||||
"react-input-mask": "^2.0.4",
|
"react-input-mask": "^2.0.4",
|
||||||
"react-markdown": "^8.0.2",
|
"react-markdown": "^8.0.3",
|
||||||
"react-photoswipe-gallery": "^2.2.1",
|
"react-photoswipe-gallery": "^2.2.1",
|
||||||
"react-redux": "^7.2.8",
|
"react-redux": "^7.2.8",
|
||||||
"react-router-dom": "^5.3.1",
|
"react-router-dom": "^5.3.1",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"react-textarea-autosize": "^8.3.3",
|
"react-textarea-autosize": "^8.3.4",
|
||||||
"redux": "^4.1.2",
|
"redux": "^4.2.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",
|
||||||
"remark-breaks": "^3.0.2",
|
"remark-breaks": "^3.0.2",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"reselect": "^4.1.5",
|
"reselect": "^4.1.6",
|
||||||
"sails.io.js": "^1.2.1",
|
"sails.io.js": "^1.2.1",
|
||||||
"semantic-ui-react": "^2.1.2",
|
"semantic-ui-react": "^2.1.3",
|
||||||
"socket.io-client": "^2.3.1",
|
"socket.io-client": "^2.3.1",
|
||||||
"validator": "^13.7.0",
|
"validator": "^13.7.0",
|
||||||
"whatwg-fetch": "^3.5.0"
|
"whatwg-fetch": "^3.6.2",
|
||||||
|
"zxcvbn": "^4.4.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.7",
|
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.7",
|
||||||
"babel-preset-airbnb": "^5.0.0",
|
"babel-preset-airbnb": "^5.0.0",
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
"enzyme": "^3.11.0",
|
"enzyme": "^3.11.0",
|
||||||
"eslint": "^8.13.0",
|
"eslint": "^8.20.0",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.26.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.5.1",
|
"eslint-plugin-jsx-a11y": "^6.6.1",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"eslint-plugin-react": "^7.29.4",
|
"eslint-plugin-react": "^7.30.1",
|
||||||
"eslint-plugin-react-hooks": "^4.4.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"jest-enzyme": "^7.1.2",
|
"jest-enzyme": "^7.1.2",
|
||||||
"prettier": "2.6.2",
|
"prettier": "2.7.1",
|
||||||
|
"react-app-rewired": "^2.2.1",
|
||||||
"react-test-renderer": "^17.0.2"
|
"react-test-renderer": "^17.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
-->
|
-->
|
||||||
<title>Planka</title>
|
<title>Planka</title>
|
||||||
</head>
|
</head>
|
||||||
|
<script>window.BASE_URL = "%PUBLIC_URL%";</script>
|
||||||
<body id="app">
|
<body id="app">
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
|
||||||
|
|
||||||
export const handleActionCreate = (action) => ({
|
|
||||||
type: ActionTypes.ACTION_CREATE_HANDLE,
|
|
||||||
payload: {
|
|
||||||
action,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const handleActionUpdate = (action) => ({
|
|
||||||
type: ActionTypes.ACTION_UPDATE_HANDLE,
|
|
||||||
payload: {
|
|
||||||
action,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const handleActionDelete = (action) => ({
|
|
||||||
type: ActionTypes.ACTION_DELETE_HANDLE,
|
|
||||||
payload: {
|
|
||||||
action,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const fetchActions = (cardId) => ({
|
|
||||||
type: ActionTypes.ACTIONS_FETCH,
|
|
||||||
payload: {
|
|
||||||
cardId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
fetchActions.success = (cardId, actions, users) => ({
|
|
||||||
type: ActionTypes.ACTIONS_FETCH__SUCCESS,
|
|
||||||
payload: {
|
|
||||||
cardId,
|
|
||||||
actions,
|
|
||||||
users,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
fetchActions.failure = (cardId, error) => ({
|
|
||||||
type: ActionTypes.ACTIONS_FETCH__FAILURE,
|
|
||||||
payload: {
|
|
||||||
cardId,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
|
const fetchActivities = (cardId) => ({
|
||||||
|
type: ActionTypes.ACTIVITIES_FETCH,
|
||||||
|
payload: {
|
||||||
|
cardId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
fetchActivities.success = (cardId, activities, users) => ({
|
||||||
|
type: ActionTypes.ACTIVITIES_FETCH__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
cardId,
|
||||||
|
activities,
|
||||||
|
users,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
fetchActivities.failure = (cardId, error) => ({
|
||||||
|
type: ActionTypes.ACTIVITIES_FETCH__FAILURE,
|
||||||
|
payload: {
|
||||||
|
cardId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const toggleActivitiesDetails = (cardId, isVisible) => ({
|
||||||
|
type: ActionTypes.ACTIVITIES_DETAILS_TOGGLE,
|
||||||
|
payload: {
|
||||||
|
cardId,
|
||||||
|
isVisible,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
toggleActivitiesDetails.success = (cardId, activities, users) => ({
|
||||||
|
type: ActionTypes.ACTIVITIES_DETAILS_TOGGLE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
cardId,
|
||||||
|
activities,
|
||||||
|
users,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
toggleActivitiesDetails.failure = (cardId, error) => ({
|
||||||
|
type: ActionTypes.ACTIVITIES_DETAILS_TOGGLE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
cardId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleActivityCreate = (activity) => ({
|
||||||
|
type: ActionTypes.ACTIVITY_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
activity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleActivityUpdate = (activity) => ({
|
||||||
|
type: ActionTypes.ACTIVITY_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
activity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleActivityDelete = (activity) => ({
|
||||||
|
type: ActionTypes.ACTIVITY_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
activity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
fetchActivities,
|
||||||
|
toggleActivitiesDetails,
|
||||||
|
handleActivityCreate,
|
||||||
|
handleActivityUpdate,
|
||||||
|
handleActivityDelete,
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const createAttachment = (attachment) => ({
|
const createAttachment = (attachment) => ({
|
||||||
type: ActionTypes.ATTACHMENT_CREATE,
|
type: ActionTypes.ATTACHMENT_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
attachment,
|
attachment,
|
||||||
@@ -23,14 +23,14 @@ createAttachment.failure = (localId, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleAttachmentCreate = (attachment) => ({
|
const handleAttachmentCreate = (attachment) => ({
|
||||||
type: ActionTypes.ATTACHMENT_CREATE_HANDLE,
|
type: ActionTypes.ATTACHMENT_CREATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
attachment,
|
attachment,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateAttachment = (id, data) => ({
|
const updateAttachment = (id, data) => ({
|
||||||
type: ActionTypes.ATTACHMENT_UPDATE,
|
type: ActionTypes.ATTACHMENT_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -53,14 +53,14 @@ updateAttachment.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleAttachmentUpdate = (attachment) => ({
|
const handleAttachmentUpdate = (attachment) => ({
|
||||||
type: ActionTypes.ATTACHMENT_UPDATE_HANDLE,
|
type: ActionTypes.ATTACHMENT_UPDATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
attachment,
|
attachment,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteAttachment = (id) => ({
|
const deleteAttachment = (id) => ({
|
||||||
type: ActionTypes.ATTACHMENT_DELETE,
|
type: ActionTypes.ATTACHMENT_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -82,9 +82,18 @@ deleteAttachment.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleAttachmentDelete = (attachment) => ({
|
const handleAttachmentDelete = (attachment) => ({
|
||||||
type: ActionTypes.ATTACHMENT_DELETE_HANDLE,
|
type: ActionTypes.ATTACHMENT_DELETE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
attachment,
|
attachment,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createAttachment,
|
||||||
|
handleAttachmentCreate,
|
||||||
|
updateAttachment,
|
||||||
|
handleAttachmentUpdate,
|
||||||
|
deleteAttachment,
|
||||||
|
handleAttachmentDelete,
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const createBoardMembership = (boardMembership) => ({
|
const createBoardMembership = (boardMembership) => ({
|
||||||
type: ActionTypes.BOARD_MEMBERSHIP_CREATE,
|
type: ActionTypes.BOARD_MEMBERSHIP_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
boardMembership,
|
boardMembership,
|
||||||
@@ -23,7 +23,7 @@ createBoardMembership.failure = (localId, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleBoardMembershipCreate = (
|
const handleBoardMembershipCreate = (
|
||||||
boardMembership,
|
boardMembership,
|
||||||
project,
|
project,
|
||||||
board,
|
board,
|
||||||
@@ -38,6 +38,7 @@ export const handleBoardMembershipCreate = (
|
|||||||
cardLabels,
|
cardLabels,
|
||||||
tasks,
|
tasks,
|
||||||
attachments,
|
attachments,
|
||||||
|
deletedNotifications,
|
||||||
) => ({
|
) => ({
|
||||||
type: ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE,
|
type: ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
@@ -55,6 +56,7 @@ export const handleBoardMembershipCreate = (
|
|||||||
cardLabels,
|
cardLabels,
|
||||||
tasks,
|
tasks,
|
||||||
attachments,
|
attachments,
|
||||||
|
deletedNotifications,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -67,7 +69,37 @@ handleBoardMembershipCreate.fetchProject = (id, currentUserId, currentBoardId) =
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteBoardMembership = (id) => ({
|
const updateBoardMembership = (id, data) => ({
|
||||||
|
type: ActionTypes.BOARD_MEMBERSHIP_UPDATE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateBoardMembership.success = (boardMembership) => ({
|
||||||
|
type: ActionTypes.BOARD_MEMBERSHIP_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
boardMembership,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateBoardMembership.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.BOARD_MEMBERSHIP_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleBoardMembershipUpdate = (boardMembership) => ({
|
||||||
|
type: ActionTypes.BOARD_MEMBERSHIP_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
boardMembership,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const deleteBoardMembership = (id) => ({
|
||||||
type: ActionTypes.BOARD_MEMBERSHIP_DELETE,
|
type: ActionTypes.BOARD_MEMBERSHIP_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -89,9 +121,18 @@ deleteBoardMembership.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleBoardMembershipDelete = (boardMembership) => ({
|
const handleBoardMembershipDelete = (boardMembership) => ({
|
||||||
type: ActionTypes.BOARD_MEMBERSHIP_DELETE_HANDLE,
|
type: ActionTypes.BOARD_MEMBERSHIP_DELETE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
boardMembership,
|
boardMembership,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createBoardMembership,
|
||||||
|
handleBoardMembershipCreate,
|
||||||
|
updateBoardMembership,
|
||||||
|
handleBoardMembershipUpdate,
|
||||||
|
deleteBoardMembership,
|
||||||
|
handleBoardMembershipDelete,
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const createBoard = (board) => ({
|
const createBoard = (board) => ({
|
||||||
type: ActionTypes.BOARD_CREATE,
|
type: ActionTypes.BOARD_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
board,
|
board,
|
||||||
@@ -24,14 +24,14 @@ createBoard.failure = (localId, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleBoardCreate = (board) => ({
|
const handleBoardCreate = (board) => ({
|
||||||
type: ActionTypes.BOARD_CREATE_HANDLE,
|
type: ActionTypes.BOARD_CREATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
board,
|
board,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const fetchBoard = (id) => ({
|
const fetchBoard = (id) => ({
|
||||||
type: ActionTypes.BOARD_FETCH,
|
type: ActionTypes.BOARD_FETCH,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -75,7 +75,7 @@ fetchBoard.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateBoard = (id, data) => ({
|
const updateBoard = (id, data) => ({
|
||||||
type: ActionTypes.BOARD_UPDATE,
|
type: ActionTypes.BOARD_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -98,14 +98,14 @@ updateBoard.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleBoardUpdate = (board) => ({
|
const handleBoardUpdate = (board) => ({
|
||||||
type: ActionTypes.BOARD_UPDATE_HANDLE,
|
type: ActionTypes.BOARD_UPDATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
board,
|
board,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteBoard = (id) => ({
|
const deleteBoard = (id) => ({
|
||||||
type: ActionTypes.BOARD_DELETE,
|
type: ActionTypes.BOARD_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -127,9 +127,19 @@ deleteBoard.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleBoardDelete = (board) => ({
|
const handleBoardDelete = (board) => ({
|
||||||
type: ActionTypes.BOARD_DELETE_HANDLE,
|
type: ActionTypes.BOARD_DELETE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
board,
|
board,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createBoard,
|
||||||
|
handleBoardCreate,
|
||||||
|
fetchBoard,
|
||||||
|
updateBoard,
|
||||||
|
handleBoardUpdate,
|
||||||
|
deleteBoard,
|
||||||
|
handleBoardDelete,
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const createCard = (card) => ({
|
const createCard = (card) => ({
|
||||||
type: ActionTypes.CARD_CREATE,
|
type: ActionTypes.CARD_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
card,
|
card,
|
||||||
@@ -23,14 +23,14 @@ createCard.failure = (localId, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleCardCreate = (card) => ({
|
const handleCardCreate = (card) => ({
|
||||||
type: ActionTypes.CARD_CREATE_HANDLE,
|
type: ActionTypes.CARD_CREATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
card,
|
card,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateCard = (id, data) => ({
|
const updateCard = (id, data) => ({
|
||||||
type: ActionTypes.CARD_UPDATE,
|
type: ActionTypes.CARD_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -53,14 +53,14 @@ updateCard.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleCardUpdate = (card) => ({
|
const handleCardUpdate = (card) => ({
|
||||||
type: ActionTypes.CARD_UPDATE_HANDLE,
|
type: ActionTypes.CARD_UPDATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
card,
|
card,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteCard = (id) => ({
|
const deleteCard = (id) => ({
|
||||||
type: ActionTypes.CARD_DELETE,
|
type: ActionTypes.CARD_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -82,9 +82,18 @@ deleteCard.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleCardDelete = (card) => ({
|
const handleCardDelete = (card) => ({
|
||||||
type: ActionTypes.CARD_DELETE_HANDLE,
|
type: ActionTypes.CARD_DELETE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
card,
|
card,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createCard,
|
||||||
|
handleCardCreate,
|
||||||
|
updateCard,
|
||||||
|
handleCardUpdate,
|
||||||
|
deleteCard,
|
||||||
|
handleCardDelete,
|
||||||
|
};
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
|
||||||
|
|
||||||
export const createCommentAction = (action) => ({
|
|
||||||
type: ActionTypes.COMMENT_ACTION_CREATE,
|
|
||||||
payload: {
|
|
||||||
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) => ({
|
|
||||||
type: ActionTypes.COMMENT_ACTION_UPDATE,
|
|
||||||
payload: {
|
|
||||||
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) => ({
|
|
||||||
type: ActionTypes.COMMENT_ACTION_DELETE,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
deleteCommentAction.success = (action) => ({
|
|
||||||
type: ActionTypes.COMMENT_ACTION_DELETE__SUCCESS,
|
|
||||||
payload: {
|
|
||||||
action,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
deleteCommentAction.failure = (id, error) => ({
|
|
||||||
type: ActionTypes.COMMENT_ACTION_DELETE__FAILURE,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
|
const createCommentActivity = (activity) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTIVITY_CREATE,
|
||||||
|
payload: {
|
||||||
|
activity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createCommentActivity.success = (localId, activity) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTIVITY_CREATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
activity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createCommentActivity.failure = (localId, error) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTIVITY_CREATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateCommentActivity = (id, data) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTIVITY_UPDATE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateCommentActivity.success = (activity) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTIVITY_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
activity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateCommentActivity.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTIVITY_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const deleteCommentActivity = (id) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTIVITY_DELETE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteCommentActivity.success = (activity) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTIVITY_DELETE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
activity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteCommentActivity.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.COMMENT_ACTIVITY_DELETE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createCommentActivity,
|
||||||
|
updateCommentActivity,
|
||||||
|
deleteCommentActivity,
|
||||||
|
};
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
const initializeCore = (
|
||||||
export const initializeCore = (
|
|
||||||
user,
|
user,
|
||||||
board,
|
board,
|
||||||
users,
|
users,
|
||||||
@@ -16,7 +15,7 @@ export const initializeCore = (
|
|||||||
cardLabels,
|
cardLabels,
|
||||||
tasks,
|
tasks,
|
||||||
attachments,
|
attachments,
|
||||||
actions,
|
activities,
|
||||||
notifications,
|
notifications,
|
||||||
) => ({
|
) => ({
|
||||||
type: ActionTypes.CORE_INITIALIZE,
|
type: ActionTypes.CORE_INITIALIZE,
|
||||||
@@ -35,7 +34,22 @@ export const initializeCore = (
|
|||||||
cardLabels,
|
cardLabels,
|
||||||
tasks,
|
tasks,
|
||||||
attachments,
|
attachments,
|
||||||
actions,
|
activities,
|
||||||
notifications,
|
notifications,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const logout = () => ({
|
||||||
|
type: ActionTypes.LOGOUT,
|
||||||
|
payload: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
logout.invalidateAccessToken = () => ({
|
||||||
|
type: ActionTypes.LOGOUT__ACCESS_TOKEN_INVALIDATE,
|
||||||
|
payload: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
initializeCore,
|
||||||
|
logout,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
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,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import EntryActionTypes from '../../constants/EntryActionTypes';
|
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const fetchActionsInCurrentCard = () => ({
|
|
||||||
type: EntryActionTypes.ACTIONS_IN_CURRENT_CARD_FETCH,
|
|
||||||
payload: {},
|
|
||||||
});
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
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,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import EntryActionTypes from '../../constants/EntryActionTypes';
|
|
||||||
|
|
||||||
export const createCommentActionInCurrentCard = (data) => ({
|
|
||||||
type: EntryActionTypes.COMMENT_ACTION_IN_CURRENT_CARD_CREATE,
|
|
||||||
payload: {
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateCommentAction = (id, data) => ({
|
|
||||||
type: EntryActionTypes.COMMENT_ACTION_UPDATE,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteCommentAction = (id) => ({
|
|
||||||
type: EntryActionTypes.COMMENT_ACTION_DELETE,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import EntryActionTypes from '../../constants/EntryActionTypes';
|
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const initializeCore = () => ({
|
|
||||||
type: EntryActionTypes.CORE_INITIALIZE,
|
|
||||||
payload: {},
|
|
||||||
});
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
export * from './socket';
|
|
||||||
export * from './login';
|
|
||||||
export * from './core';
|
|
||||||
export * from './modal';
|
|
||||||
export * from './user';
|
|
||||||
export * from './project';
|
|
||||||
export * from './project-manager';
|
|
||||||
export * from './board';
|
|
||||||
export * from './board-membership';
|
|
||||||
export * from './label';
|
|
||||||
export * from './list';
|
|
||||||
export * from './card';
|
|
||||||
export * from './task';
|
|
||||||
export * from './attachment';
|
|
||||||
export * from './actions';
|
|
||||||
export * from './action';
|
|
||||||
export * from './comment-action';
|
|
||||||
export * from './notification';
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import EntryActionTypes from '../../constants/EntryActionTypes';
|
|
||||||
|
|
||||||
export const authenticate = (data) => ({
|
|
||||||
type: EntryActionTypes.AUTHENTICATE,
|
|
||||||
payload: {
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const clearAuthenticateError = () => ({
|
|
||||||
type: EntryActionTypes.AUTHENTICATE_ERROR_CLEAR,
|
|
||||||
payload: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const logout = () => ({
|
|
||||||
type: EntryActionTypes.LOGOUT,
|
|
||||||
payload: {},
|
|
||||||
});
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import EntryActionTypes from '../../constants/EntryActionTypes';
|
|
||||||
|
|
||||||
export const handleNotificationCreate = (notification) => ({
|
|
||||||
type: EntryActionTypes.NOTIFICATION_CREATE_HANDLE,
|
|
||||||
payload: {
|
|
||||||
notification,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteNotification = (id) => ({
|
|
||||||
type: EntryActionTypes.NOTIFICATION_DELETE,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const handleNotificationDelete = (notification) => ({
|
|
||||||
type: EntryActionTypes.NOTIFICATION_DELETE_HANDLE,
|
|
||||||
payload: {
|
|
||||||
notification,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
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,11 +0,0 @@
|
|||||||
import EntryActionTypes from '../../constants/EntryActionTypes';
|
|
||||||
|
|
||||||
export const handleSocketDisconnect = () => ({
|
|
||||||
type: EntryActionTypes.SOCKET_DISCONNECT_HANDLE,
|
|
||||||
payload: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const handleSocketReconnect = () => ({
|
|
||||||
type: EntryActionTypes.SOCKET_RECONNECT_HANDLE,
|
|
||||||
payload: {},
|
|
||||||
});
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
import EntryActionTypes from '../../constants/EntryActionTypes';
|
|
||||||
|
|
||||||
export const createTaskInCurrentCard = (data) => ({
|
|
||||||
type: EntryActionTypes.TASK_IN_CURRENT_CARD_CREATE,
|
|
||||||
payload: {
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const handleTaskCreate = (task) => ({
|
|
||||||
type: EntryActionTypes.TASK_CREATE_HANDLE,
|
|
||||||
payload: {
|
|
||||||
task,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateTask = (id, data) => ({
|
|
||||||
type: EntryActionTypes.TASK_UPDATE,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const handleTaskUpdate = (task) => ({
|
|
||||||
type: EntryActionTypes.TASK_UPDATE_HANDLE,
|
|
||||||
payload: {
|
|
||||||
task,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteTask = (id) => ({
|
|
||||||
type: EntryActionTypes.TASK_DELETE,
|
|
||||||
payload: {
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const handleTaskDelete = (task) => ({
|
|
||||||
type: EntryActionTypes.TASK_DELETE_HANDLE,
|
|
||||||
payload: {
|
|
||||||
task,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
+39
-19
@@ -1,19 +1,39 @@
|
|||||||
export * from './router';
|
import router from './router';
|
||||||
export * from './socket';
|
import socket from './socket';
|
||||||
export * from './login';
|
import login from './login';
|
||||||
export * from './core';
|
import core from './core';
|
||||||
export * from './modal';
|
import modals from './modals';
|
||||||
export * from './user';
|
import users from './users';
|
||||||
export * from './project';
|
import projects from './projects';
|
||||||
export * from './project-manager';
|
import projectManagers from './project-managers';
|
||||||
export * from './board';
|
import boards from './boards';
|
||||||
export * from './board-membership';
|
import boardMemberships from './board-memberships';
|
||||||
export * from './label';
|
import labels from './labels';
|
||||||
export * from './list';
|
import lists from './lists';
|
||||||
export * from './card';
|
import cards from './cards';
|
||||||
export * from './task';
|
import tasks from './tasks';
|
||||||
export * from './attachment';
|
import attachments from './attachments';
|
||||||
export * from './actions';
|
import activities from './activities';
|
||||||
export * from './action';
|
import commentActivities from './comment-activities';
|
||||||
export * from './comment-action';
|
import notifications from './notifications';
|
||||||
export * from './notification';
|
|
||||||
|
export default {
|
||||||
|
...router,
|
||||||
|
...socket,
|
||||||
|
...login,
|
||||||
|
...core,
|
||||||
|
...modals,
|
||||||
|
...users,
|
||||||
|
...projects,
|
||||||
|
...projectManagers,
|
||||||
|
...boards,
|
||||||
|
...boardMemberships,
|
||||||
|
...labels,
|
||||||
|
...lists,
|
||||||
|
...cards,
|
||||||
|
...tasks,
|
||||||
|
...attachments,
|
||||||
|
...activities,
|
||||||
|
...commentActivities,
|
||||||
|
...notifications,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const createLabel = (label) => ({
|
const createLabel = (label) => ({
|
||||||
type: ActionTypes.LABEL_CREATE,
|
type: ActionTypes.LABEL_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
label,
|
label,
|
||||||
@@ -23,14 +23,14 @@ createLabel.failure = (localId, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleLabelCreate = (label) => ({
|
const handleLabelCreate = (label) => ({
|
||||||
type: ActionTypes.LABEL_CREATE_HANDLE,
|
type: ActionTypes.LABEL_CREATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
label,
|
label,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateLabel = (id, data) => ({
|
const updateLabel = (id, data) => ({
|
||||||
type: ActionTypes.LABEL_UPDATE,
|
type: ActionTypes.LABEL_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -53,14 +53,14 @@ updateLabel.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleLabelUpdate = (label) => ({
|
const handleLabelUpdate = (label) => ({
|
||||||
type: ActionTypes.LABEL_UPDATE_HANDLE,
|
type: ActionTypes.LABEL_UPDATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
label,
|
label,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteLabel = (id) => ({
|
const deleteLabel = (id) => ({
|
||||||
type: ActionTypes.LABEL_DELETE,
|
type: ActionTypes.LABEL_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -82,14 +82,14 @@ deleteLabel.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleLabelDelete = (label) => ({
|
const handleLabelDelete = (label) => ({
|
||||||
type: ActionTypes.LABEL_DELETE_HANDLE,
|
type: ActionTypes.LABEL_DELETE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
label,
|
label,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const addLabelToCard = (id, cardId) => ({
|
const addLabelToCard = (id, cardId) => ({
|
||||||
type: ActionTypes.LABEL_TO_CARD_ADD,
|
type: ActionTypes.LABEL_TO_CARD_ADD,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -113,14 +113,14 @@ addLabelToCard.failure = (id, cardId, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleLabelToCardAdd = (cardLabel) => ({
|
const handleLabelToCardAdd = (cardLabel) => ({
|
||||||
type: ActionTypes.LABEL_TO_CARD_ADD_HANDLE,
|
type: ActionTypes.LABEL_TO_CARD_ADD_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
cardLabel,
|
cardLabel,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const removeLabelFromCard = (id, cardId) => ({
|
const removeLabelFromCard = (id, cardId) => ({
|
||||||
type: ActionTypes.LABEL_FROM_CARD_REMOVE,
|
type: ActionTypes.LABEL_FROM_CARD_REMOVE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -144,14 +144,14 @@ removeLabelFromCard.failure = (id, cardId, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleLabelFromCardRemove = (cardLabel) => ({
|
const handleLabelFromCardRemove = (cardLabel) => ({
|
||||||
type: ActionTypes.LABEL_FROM_CARD_REMOVE_HANDLE,
|
type: ActionTypes.LABEL_FROM_CARD_REMOVE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
cardLabel,
|
cardLabel,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const addLabelToBoardFilter = (id, boardId) => ({
|
const addLabelToBoardFilter = (id, boardId) => ({
|
||||||
type: ActionTypes.LABEL_TO_BOARD_FILTER_ADD,
|
type: ActionTypes.LABEL_TO_BOARD_FILTER_ADD,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -159,10 +159,25 @@ export const addLabelToBoardFilter = (id, boardId) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const removeLabelFromBoardFilter = (id, boardId) => ({
|
const removeLabelFromBoardFilter = (id, boardId) => ({
|
||||||
type: ActionTypes.LABEL_FROM_BOARD_FILTER_REMOVE,
|
type: ActionTypes.LABEL_FROM_BOARD_FILTER_REMOVE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
boardId,
|
boardId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createLabel,
|
||||||
|
handleLabelCreate,
|
||||||
|
updateLabel,
|
||||||
|
handleLabelUpdate,
|
||||||
|
deleteLabel,
|
||||||
|
handleLabelDelete,
|
||||||
|
addLabelToCard,
|
||||||
|
handleLabelToCardAdd,
|
||||||
|
removeLabelFromCard,
|
||||||
|
handleLabelFromCardRemove,
|
||||||
|
addLabelToBoardFilter,
|
||||||
|
removeLabelFromBoardFilter,
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const createList = (list) => ({
|
const createList = (list) => ({
|
||||||
type: ActionTypes.LIST_CREATE,
|
type: ActionTypes.LIST_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
list,
|
list,
|
||||||
@@ -23,14 +23,14 @@ createList.failure = (localId, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleListCreate = (list) => ({
|
const handleListCreate = (list) => ({
|
||||||
type: ActionTypes.LIST_CREATE_HANDLE,
|
type: ActionTypes.LIST_CREATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
list,
|
list,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateList = (id, data) => ({
|
const updateList = (id, data) => ({
|
||||||
type: ActionTypes.LIST_UPDATE,
|
type: ActionTypes.LIST_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -53,14 +53,14 @@ updateList.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleListUpdate = (list) => ({
|
const handleListUpdate = (list) => ({
|
||||||
type: ActionTypes.LIST_UPDATE_HANDLE,
|
type: ActionTypes.LIST_UPDATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
list,
|
list,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteList = (id) => ({
|
const deleteList = (id) => ({
|
||||||
type: ActionTypes.LIST_DELETE,
|
type: ActionTypes.LIST_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -82,9 +82,18 @@ deleteList.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleListDelete = (list) => ({
|
const handleListDelete = (list) => ({
|
||||||
type: ActionTypes.LIST_DELETE_HANDLE,
|
type: ActionTypes.LIST_DELETE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
list,
|
list,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createList,
|
||||||
|
handleListCreate,
|
||||||
|
updateList,
|
||||||
|
handleListUpdate,
|
||||||
|
deleteList,
|
||||||
|
handleListDelete,
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const authenticate = (data) => ({
|
const authenticate = (data) => ({
|
||||||
type: ActionTypes.AUTHENTICATE,
|
type: ActionTypes.AUTHENTICATE,
|
||||||
payload: {
|
payload: {
|
||||||
data,
|
data,
|
||||||
@@ -21,12 +21,12 @@ authenticate.failure = (error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const clearAuthenticateError = () => ({
|
const clearAuthenticateError = () => ({
|
||||||
type: ActionTypes.AUTHENTICATE_ERROR_CLEAR,
|
type: ActionTypes.AUTHENTICATE_ERROR_CLEAR,
|
||||||
payload: {},
|
payload: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const logout = () => ({
|
export default {
|
||||||
type: ActionTypes.LOGOUT,
|
authenticate,
|
||||||
payload: {},
|
clearAuthenticateError,
|
||||||
});
|
};
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const openModal = (type) => ({
|
const openModal = (type) => ({
|
||||||
type: ActionTypes.MODAL_OPEN,
|
type: ActionTypes.MODAL_OPEN,
|
||||||
payload: {
|
payload: {
|
||||||
type,
|
type,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const closeModal = () => ({
|
const closeModal = () => ({
|
||||||
type: ActionTypes.MODAL_CLOSE,
|
type: ActionTypes.MODAL_CLOSE,
|
||||||
payload: {},
|
payload: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
openModal,
|
||||||
|
closeModal,
|
||||||
|
};
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const handleNotificationCreate = (notification, users, cards, actions) => ({
|
const handleNotificationCreate = (notification, users, cards, activities) => ({
|
||||||
type: ActionTypes.NOTIFICATION_CREATE_HANDLE,
|
type: ActionTypes.NOTIFICATION_CREATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
notification,
|
notification,
|
||||||
users,
|
users,
|
||||||
cards,
|
cards,
|
||||||
actions,
|
activities,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteNotification = (id) => ({
|
const deleteNotification = (id) => ({
|
||||||
type: ActionTypes.NOTIFICATION_DELETE,
|
type: ActionTypes.NOTIFICATION_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -32,9 +32,15 @@ deleteNotification.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleNotificationDelete = (notification) => ({
|
const handleNotificationDelete = (notification) => ({
|
||||||
type: ActionTypes.NOTIFICATION_DELETE_HANDLE,
|
type: ActionTypes.NOTIFICATION_DELETE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
notification,
|
notification,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
handleNotificationCreate,
|
||||||
|
deleteNotification,
|
||||||
|
handleNotificationDelete,
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const createProjectManager = (projectManager) => ({
|
const createProjectManager = (projectManager) => ({
|
||||||
type: ActionTypes.PROJECT_MANAGER_CREATE,
|
type: ActionTypes.PROJECT_MANAGER_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
projectManager,
|
projectManager,
|
||||||
@@ -23,7 +23,7 @@ createProjectManager.failure = (localId, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleProjectManagerCreate = (
|
const handleProjectManagerCreate = (
|
||||||
projectManager,
|
projectManager,
|
||||||
project,
|
project,
|
||||||
board,
|
board,
|
||||||
@@ -38,6 +38,7 @@ export const handleProjectManagerCreate = (
|
|||||||
cardLabels,
|
cardLabels,
|
||||||
tasks,
|
tasks,
|
||||||
attachments,
|
attachments,
|
||||||
|
deletedNotifications,
|
||||||
) => ({
|
) => ({
|
||||||
type: ActionTypes.PROJECT_MANAGER_CREATE_HANDLE,
|
type: ActionTypes.PROJECT_MANAGER_CREATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
@@ -55,6 +56,7 @@ export const handleProjectManagerCreate = (
|
|||||||
cardLabels,
|
cardLabels,
|
||||||
tasks,
|
tasks,
|
||||||
attachments,
|
attachments,
|
||||||
|
deletedNotifications,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -67,7 +69,7 @@ handleProjectManagerCreate.fetchProject = (id, currentUserId, currentBoardId) =>
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteProjectManager = (id, isCurrentUser, isCurrentProject) => ({
|
const deleteProjectManager = (id, isCurrentUser, isCurrentProject) => ({
|
||||||
type: ActionTypes.PROJECT_MANAGER_DELETE,
|
type: ActionTypes.PROJECT_MANAGER_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -91,7 +93,7 @@ deleteProjectManager.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleProjectManagerDelete = (projectManager, isCurrentUser, isCurrentProject) => ({
|
const handleProjectManagerDelete = (projectManager, isCurrentUser, isCurrentProject) => ({
|
||||||
type: ActionTypes.PROJECT_MANAGER_DELETE_HANDLE,
|
type: ActionTypes.PROJECT_MANAGER_DELETE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
projectManager,
|
projectManager,
|
||||||
@@ -99,3 +101,10 @@ export const handleProjectManagerDelete = (projectManager, isCurrentUser, isCurr
|
|||||||
isCurrentProject,
|
isCurrentProject,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createProjectManager,
|
||||||
|
handleProjectManagerCreate,
|
||||||
|
deleteProjectManager,
|
||||||
|
handleProjectManagerDelete,
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const createProject = (data) => ({
|
const createProject = (data) => ({
|
||||||
type: ActionTypes.PROJECT_CREATE,
|
type: ActionTypes.PROJECT_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
data,
|
data,
|
||||||
@@ -22,7 +22,7 @@ createProject.failure = (error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleProjectCreate = (project, users, projectManagers, boards, boardMemberships) => ({
|
const handleProjectCreate = (project, users, projectManagers, boards, boardMemberships) => ({
|
||||||
type: ActionTypes.PROJECT_CREATE_HANDLE,
|
type: ActionTypes.PROJECT_CREATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
project,
|
project,
|
||||||
@@ -33,7 +33,7 @@ export const handleProjectCreate = (project, users, projectManagers, boards, boa
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateProject = (id, data) => ({
|
const updateProject = (id, data) => ({
|
||||||
type: ActionTypes.PROJECT_UPDATE,
|
type: ActionTypes.PROJECT_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -56,14 +56,14 @@ updateProject.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleProjectUpdate = (project) => ({
|
const handleProjectUpdate = (project) => ({
|
||||||
type: ActionTypes.PROJECT_UPDATE_HANDLE,
|
type: ActionTypes.PROJECT_UPDATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
project,
|
project,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateProjectBackgroundImage = (id) => ({
|
const updateProjectBackgroundImage = (id) => ({
|
||||||
type: ActionTypes.PROJECT_BACKGROUND_IMAGE_UPDATE,
|
type: ActionTypes.PROJECT_BACKGROUND_IMAGE_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -85,7 +85,7 @@ updateProjectBackgroundImage.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteProject = (id) => ({
|
const deleteProject = (id) => ({
|
||||||
type: ActionTypes.PROJECT_DELETE,
|
type: ActionTypes.PROJECT_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -107,9 +107,19 @@ deleteProject.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleProjectDelete = (project) => ({
|
const handleProjectDelete = (project) => ({
|
||||||
type: ActionTypes.PROJECT_DELETE_HANDLE,
|
type: ActionTypes.PROJECT_DELETE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
project,
|
project,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createProject,
|
||||||
|
handleProjectCreate,
|
||||||
|
updateProject,
|
||||||
|
handleProjectUpdate,
|
||||||
|
updateProjectBackgroundImage,
|
||||||
|
deleteProject,
|
||||||
|
handleProjectDelete,
|
||||||
|
};
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
const handleLocationChange = (
|
||||||
export const handleLocationChange = (
|
|
||||||
board,
|
board,
|
||||||
users,
|
users,
|
||||||
projects,
|
projects,
|
||||||
@@ -13,7 +12,7 @@ export const handleLocationChange = (
|
|||||||
cardLabels,
|
cardLabels,
|
||||||
tasks,
|
tasks,
|
||||||
attachments,
|
attachments,
|
||||||
notifications,
|
deletedNotifications,
|
||||||
) => ({
|
) => ({
|
||||||
type: ActionTypes.LOCATION_CHANGE_HANDLE,
|
type: ActionTypes.LOCATION_CHANGE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
@@ -28,7 +27,7 @@ export const handleLocationChange = (
|
|||||||
cardLabels,
|
cardLabels,
|
||||||
tasks,
|
tasks,
|
||||||
attachments,
|
attachments,
|
||||||
notifications,
|
deletedNotifications,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -38,3 +37,7 @@ handleLocationChange.fetchBoard = (id) => ({
|
|||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
handleLocationChange,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const handleSocketDisconnect = () => ({
|
const handleSocketDisconnect = () => ({
|
||||||
type: ActionTypes.SOCKET_DISCONNECT_HANDLE,
|
type: ActionTypes.SOCKET_DISCONNECT_HANDLE,
|
||||||
payload: {},
|
payload: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleSocketReconnect = (
|
const handleSocketReconnect = (
|
||||||
user,
|
user,
|
||||||
board,
|
board,
|
||||||
users,
|
users,
|
||||||
@@ -20,7 +20,7 @@ export const handleSocketReconnect = (
|
|||||||
cardLabels,
|
cardLabels,
|
||||||
tasks,
|
tasks,
|
||||||
attachments,
|
attachments,
|
||||||
actions,
|
activities,
|
||||||
notifications,
|
notifications,
|
||||||
) => ({
|
) => ({
|
||||||
type: ActionTypes.SOCKET_RECONNECT_HANDLE,
|
type: ActionTypes.SOCKET_RECONNECT_HANDLE,
|
||||||
@@ -39,7 +39,7 @@ export const handleSocketReconnect = (
|
|||||||
cardLabels,
|
cardLabels,
|
||||||
tasks,
|
tasks,
|
||||||
attachments,
|
attachments,
|
||||||
actions,
|
activities,
|
||||||
notifications,
|
notifications,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -51,3 +51,8 @@ handleSocketReconnect.fetchCore = (currentUserId, currentBoardId) => ({
|
|||||||
currentBoardId,
|
currentBoardId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
handleSocketDisconnect,
|
||||||
|
handleSocketReconnect,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const createTask = (task) => ({
|
const createTask = (task) => ({
|
||||||
type: ActionTypes.TASK_CREATE,
|
type: ActionTypes.TASK_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
task,
|
task,
|
||||||
@@ -23,14 +23,14 @@ createTask.failure = (localId, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleTaskCreate = (task) => ({
|
const handleTaskCreate = (task) => ({
|
||||||
type: ActionTypes.TASK_CREATE_HANDLE,
|
type: ActionTypes.TASK_CREATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
task,
|
task,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateTask = (id, data) => ({
|
const updateTask = (id, data) => ({
|
||||||
type: ActionTypes.TASK_UPDATE,
|
type: ActionTypes.TASK_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -53,14 +53,14 @@ updateTask.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleTaskUpdate = (task) => ({
|
const handleTaskUpdate = (task) => ({
|
||||||
type: ActionTypes.TASK_UPDATE_HANDLE,
|
type: ActionTypes.TASK_UPDATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
task,
|
task,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteTask = (id) => ({
|
const deleteTask = (id) => ({
|
||||||
type: ActionTypes.TASK_DELETE,
|
type: ActionTypes.TASK_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -82,9 +82,18 @@ deleteTask.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleTaskDelete = (task) => ({
|
const handleTaskDelete = (task) => ({
|
||||||
type: ActionTypes.TASK_DELETE_HANDLE,
|
type: ActionTypes.TASK_DELETE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
task,
|
task,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createTask,
|
||||||
|
handleTaskCreate,
|
||||||
|
updateTask,
|
||||||
|
handleTaskUpdate,
|
||||||
|
deleteTask,
|
||||||
|
handleTaskDelete,
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import ActionTypes from '../constants/ActionTypes';
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
export const createUser = (data) => ({
|
const createUser = (data) => ({
|
||||||
type: ActionTypes.USER_CREATE,
|
type: ActionTypes.USER_CREATE,
|
||||||
payload: {
|
payload: {
|
||||||
data,
|
data,
|
||||||
@@ -21,19 +21,19 @@ createUser.failure = (error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleUserCreate = (user) => ({
|
const handleUserCreate = (user) => ({
|
||||||
type: ActionTypes.USER_CREATE_HANDLE,
|
type: ActionTypes.USER_CREATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
user,
|
user,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const clearUserCreateError = () => ({
|
const clearUserCreateError = () => ({
|
||||||
type: ActionTypes.USER_CREATE_ERROR_CLEAR,
|
type: ActionTypes.USER_CREATE_ERROR_CLEAR,
|
||||||
payload: {},
|
payload: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateUser = (id, data) => ({
|
const updateUser = (id, data) => ({
|
||||||
type: ActionTypes.USER_UPDATE,
|
type: ActionTypes.USER_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -56,7 +56,7 @@ updateUser.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleUserUpdate = (user, users, isCurrent) => ({
|
const handleUserUpdate = (user, users, isCurrent) => ({
|
||||||
type: ActionTypes.USER_UPDATE_HANDLE,
|
type: ActionTypes.USER_UPDATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
user,
|
user,
|
||||||
@@ -65,7 +65,7 @@ export const handleUserUpdate = (user, users, isCurrent) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateUserEmail = (id, data) => ({
|
const updateUserEmail = (id, data) => ({
|
||||||
type: ActionTypes.USER_EMAIL_UPDATE,
|
type: ActionTypes.USER_EMAIL_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -88,14 +88,14 @@ updateUserEmail.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const clearUserEmailUpdateError = (id) => ({
|
const clearUserEmailUpdateError = (id) => ({
|
||||||
type: ActionTypes.USER_EMAIL_UPDATE_ERROR_CLEAR,
|
type: ActionTypes.USER_EMAIL_UPDATE_ERROR_CLEAR,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateUserPassword = (id, data) => ({
|
const updateUserPassword = (id, data) => ({
|
||||||
type: ActionTypes.USER_PASSWORD_UPDATE,
|
type: ActionTypes.USER_PASSWORD_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -103,10 +103,11 @@ export const updateUserPassword = (id, data) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
updateUserPassword.success = (user) => ({
|
updateUserPassword.success = (user, accessToken) => ({
|
||||||
type: ActionTypes.USER_PASSWORD_UPDATE__SUCCESS,
|
type: ActionTypes.USER_PASSWORD_UPDATE__SUCCESS,
|
||||||
payload: {
|
payload: {
|
||||||
user,
|
user,
|
||||||
|
accessToken,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -118,14 +119,14 @@ updateUserPassword.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const clearUserPasswordUpdateError = (id) => ({
|
const clearUserPasswordUpdateError = (id) => ({
|
||||||
type: ActionTypes.USER_PASSWORD_UPDATE_ERROR_CLEAR,
|
type: ActionTypes.USER_PASSWORD_UPDATE_ERROR_CLEAR,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateUserUsername = (id, data) => ({
|
const updateUserUsername = (id, data) => ({
|
||||||
type: ActionTypes.USER_USERNAME_UPDATE,
|
type: ActionTypes.USER_USERNAME_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -148,14 +149,14 @@ updateUserUsername.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const clearUserUsernameUpdateError = (id) => ({
|
const clearUserUsernameUpdateError = (id) => ({
|
||||||
type: ActionTypes.USER_USERNAME_UPDATE_ERROR_CLEAR,
|
type: ActionTypes.USER_USERNAME_UPDATE_ERROR_CLEAR,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateUserAvatar = (id) => ({
|
const updateUserAvatar = (id) => ({
|
||||||
type: ActionTypes.USER_AVATAR_UPDATE,
|
type: ActionTypes.USER_AVATAR_UPDATE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -177,7 +178,7 @@ updateUserAvatar.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteUser = (id) => ({
|
const deleteUser = (id) => ({
|
||||||
type: ActionTypes.USER_DELETE,
|
type: ActionTypes.USER_DELETE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -199,14 +200,14 @@ deleteUser.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleUserDelete = (user) => ({
|
const handleUserDelete = (user) => ({
|
||||||
type: ActionTypes.USER_DELETE_HANDLE,
|
type: ActionTypes.USER_DELETE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
user,
|
user,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const addUserToCard = (id, cardId, isCurrent) => ({
|
const addUserToCard = (id, cardId, isCurrent) => ({
|
||||||
type: ActionTypes.USER_TO_CARD_ADD,
|
type: ActionTypes.USER_TO_CARD_ADD,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -231,14 +232,14 @@ addUserToCard.failure = (id, cardId, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleUserToCardAdd = (cardMembership) => ({
|
const handleUserToCardAdd = (cardMembership) => ({
|
||||||
type: ActionTypes.USER_TO_CARD_ADD_HANDLE,
|
type: ActionTypes.USER_TO_CARD_ADD_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
cardMembership,
|
cardMembership,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const removeUserFromCard = (id, cardId) => ({
|
const removeUserFromCard = (id, cardId) => ({
|
||||||
type: ActionTypes.USER_FROM_CARD_REMOVE,
|
type: ActionTypes.USER_FROM_CARD_REMOVE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -262,14 +263,14 @@ removeUserFromCard.failure = (id, cardId, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const handleUserFromCardRemove = (cardMembership) => ({
|
const handleUserFromCardRemove = (cardMembership) => ({
|
||||||
type: ActionTypes.USER_FROM_CARD_REMOVE_HANDLE,
|
type: ActionTypes.USER_FROM_CARD_REMOVE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
cardMembership,
|
cardMembership,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const addUserToBoardFilter = (id, boardId) => ({
|
const addUserToBoardFilter = (id, boardId) => ({
|
||||||
type: ActionTypes.USER_TO_BOARD_FILTER_ADD,
|
type: ActionTypes.USER_TO_BOARD_FILTER_ADD,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
@@ -277,10 +278,33 @@ export const addUserToBoardFilter = (id, boardId) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const removeUserFromBoardFilter = (id, boardId) => ({
|
const removeUserFromBoardFilter = (id, boardId) => ({
|
||||||
type: ActionTypes.USER_FROM_BOARD_FILTER_REMOVE,
|
type: ActionTypes.USER_FROM_BOARD_FILTER_REMOVE,
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
id,
|
||||||
boardId,
|
boardId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createUser,
|
||||||
|
handleUserCreate,
|
||||||
|
clearUserCreateError,
|
||||||
|
updateUser,
|
||||||
|
handleUserUpdate,
|
||||||
|
updateUserEmail,
|
||||||
|
clearUserEmailUpdateError,
|
||||||
|
updateUserPassword,
|
||||||
|
clearUserPasswordUpdateError,
|
||||||
|
updateUserUsername,
|
||||||
|
clearUserUsernameUpdateError,
|
||||||
|
updateUserAvatar,
|
||||||
|
deleteUser,
|
||||||
|
handleUserDelete,
|
||||||
|
addUserToCard,
|
||||||
|
handleUserToCardAdd,
|
||||||
|
removeUserFromCard,
|
||||||
|
handleUserFromCardRemove,
|
||||||
|
addUserToBoardFilter,
|
||||||
|
removeUserFromBoardFilter,
|
||||||
|
};
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
import http from './http';
|
import http from './http';
|
||||||
|
import socket from './socket';
|
||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const createAccessToken = (data) => http.post('/access-tokens', data);
|
const createAccessToken = (data, headers) => http.post('/access-tokens', data, headers);
|
||||||
|
|
||||||
|
const deleteCurrentAccessToken = (headers) =>
|
||||||
|
socket.delete('/access-tokens/me', undefined, headers);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createAccessToken,
|
createAccessToken,
|
||||||
|
deleteCurrentAccessToken,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
import socket from './socket';
|
|
||||||
|
|
||||||
/* Transformers */
|
|
||||||
|
|
||||||
export const transformAction = (action) => ({
|
|
||||||
...action,
|
|
||||||
createdAt: new Date(action.createdAt),
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
const getActions = (cardId, data) =>
|
|
||||||
socket.get(`/cards/${cardId}/actions`, data).then((body) => ({
|
|
||||||
...body,
|
|
||||||
items: body.items.map(transformAction),
|
|
||||||
}));
|
|
||||||
|
|
||||||
/* Event handlers */
|
|
||||||
|
|
||||||
const makeHandleActionCreate = (next) => (body) => {
|
|
||||||
next({
|
|
||||||
...body,
|
|
||||||
item: transformAction(body.item),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const makeHandleActionUpdate = makeHandleActionCreate;
|
|
||||||
|
|
||||||
const makeHandleActionDelete = makeHandleActionCreate;
|
|
||||||
|
|
||||||
export default {
|
|
||||||
getActions,
|
|
||||||
makeHandleActionCreate,
|
|
||||||
makeHandleActionUpdate,
|
|
||||||
makeHandleActionDelete,
|
|
||||||
};
|
|
||||||
Executable
+36
@@ -0,0 +1,36 @@
|
|||||||
|
import socket from './socket';
|
||||||
|
|
||||||
|
/* Transformers */
|
||||||
|
|
||||||
|
export const transformActivity = (activity) => ({
|
||||||
|
...activity,
|
||||||
|
createdAt: new Date(activity.createdAt),
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Actions */
|
||||||
|
|
||||||
|
const getActivities = (cardId, data, headers) =>
|
||||||
|
socket.get(`/cards/${cardId}/actions`, data, headers).then((body) => ({
|
||||||
|
...body,
|
||||||
|
items: body.items.map(transformActivity),
|
||||||
|
}));
|
||||||
|
|
||||||
|
/* Event handlers */
|
||||||
|
|
||||||
|
const makeHandleActivityCreate = (next) => (body) => {
|
||||||
|
next({
|
||||||
|
...body,
|
||||||
|
item: transformActivity(body.item),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeHandleActivityUpdate = makeHandleActivityCreate;
|
||||||
|
|
||||||
|
const makeHandleActivityDelete = makeHandleActivityCreate;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getActivities,
|
||||||
|
makeHandleActivityCreate,
|
||||||
|
makeHandleActivityUpdate,
|
||||||
|
makeHandleActivityDelete,
|
||||||
|
};
|
||||||
@@ -10,20 +10,20 @@ export const transformAttachment = (attachment) => ({
|
|||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const createAttachment = (cardId, data, requestId) =>
|
const createAttachment = (cardId, data, requestId, headers) =>
|
||||||
http.post(`/cards/${cardId}/attachments?requestId=${requestId}`, data).then((body) => ({
|
http.post(`/cards/${cardId}/attachments?requestId=${requestId}`, data, headers).then((body) => ({
|
||||||
...body,
|
...body,
|
||||||
item: transformAttachment(body.item),
|
item: transformAttachment(body.item),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const updateAttachment = (id, data) =>
|
const updateAttachment = (id, data, headers) =>
|
||||||
socket.patch(`/attachments/${id}`, data).then((body) => ({
|
socket.patch(`/attachments/${id}`, data, headers).then((body) => ({
|
||||||
...body,
|
...body,
|
||||||
item: transformAttachment(body.item),
|
item: transformAttachment(body.item),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const deleteAttachment = (id) =>
|
const deleteAttachment = (id, headers) =>
|
||||||
socket.delete(`/attachments/${id}`).then((body) => ({
|
socket.delete(`/attachments/${id}`, undefined, headers).then((body) => ({
|
||||||
...body,
|
...body,
|
||||||
item: transformAttachment(body.item),
|
item: transformAttachment(body.item),
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -2,12 +2,17 @@ import socket from './socket';
|
|||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const createBoardMembership = (boardId, data) =>
|
const createBoardMembership = (boardId, data, headers) =>
|
||||||
socket.post(`/boards/${boardId}/memberships`, data);
|
socket.post(`/boards/${boardId}/memberships`, data, headers);
|
||||||
|
|
||||||
const deleteBoardMembership = (id) => socket.delete(`/board-memberships/${id}`);
|
const updateBoardMembership = (id, data, headers) =>
|
||||||
|
socket.patch(`/board-memberships/${id}`, data, headers);
|
||||||
|
|
||||||
|
const deleteBoardMembership = (id, headers) =>
|
||||||
|
socket.delete(`/board-memberships/${id}`, undefined, headers);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createBoardMembership,
|
createBoardMembership,
|
||||||
|
updateBoardMembership,
|
||||||
deleteBoardMembership,
|
deleteBoardMembership,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ import { transformAttachment } from './attachments';
|
|||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const createBoard = (projectId, data) => socket.post(`/projects/${projectId}/boards`, data);
|
const createBoard = (projectId, data, headers) =>
|
||||||
|
socket.post(`/projects/${projectId}/boards`, data, headers);
|
||||||
|
|
||||||
const getBoard = (id) =>
|
const getBoard = (id, headers) =>
|
||||||
socket.get(`/boards/${id}`).then((body) => ({
|
socket.get(`/boards/${id}`, undefined, headers).then((body) => ({
|
||||||
...body,
|
...body,
|
||||||
included: {
|
included: {
|
||||||
...body.included,
|
...body.included,
|
||||||
@@ -16,9 +17,9 @@ const getBoard = (id) =>
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const updateBoard = (id, data) => socket.patch(`/boards/${id}`, data);
|
const updateBoard = (id, data, headers) => socket.patch(`/boards/${id}`, data, headers);
|
||||||
|
|
||||||
const deleteBoard = (id) => socket.delete(`/boards/${id}`);
|
const deleteBoard = (id, headers) => socket.delete(`/boards/${id}`, undefined, headers);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createBoard,
|
createBoard,
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ import socket from './socket';
|
|||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const createCardLabel = (cardId, data) => socket.post(`/cards/${cardId}/labels`, data);
|
const createCardLabel = (cardId, data, headers) =>
|
||||||
|
socket.post(`/cards/${cardId}/labels`, data, headers);
|
||||||
|
|
||||||
const deleteCardLabel = (cardId, labelId) => socket.delete(`/cards/${cardId}/labels/${labelId}`);
|
const deleteCardLabel = (cardId, labelId, headers) =>
|
||||||
|
socket.delete(`/cards/${cardId}/labels/${labelId}`, undefined, headers);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createCardLabel,
|
createCardLabel,
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ import socket from './socket';
|
|||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const createCardMembership = (cardId, data) => socket.post(`/cards/${cardId}/memberships`, data);
|
const createCardMembership = (cardId, data, headers) =>
|
||||||
|
socket.post(`/cards/${cardId}/memberships`, data, headers);
|
||||||
|
|
||||||
const deleteCardMembership = (cardId, userId) =>
|
const deleteCardMembership = (cardId, userId, headers) =>
|
||||||
socket.delete(`/cards/${cardId}/memberships?userId=${userId}`);
|
socket.delete(`/cards/${cardId}/memberships?userId=${userId}`, undefined, headers);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createCardMembership,
|
createCardMembership,
|
||||||
|
|||||||
+12
-17
@@ -35,8 +35,8 @@ export const transformCardData = (data) => ({
|
|||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const getCards = (boardId, data) =>
|
const getCards = (boardId, data, headers) =>
|
||||||
socket.get(`/board/${boardId}/cards`, data).then((body) => ({
|
socket.get(`/board/${boardId}/cards`, data, headers).then((body) => ({
|
||||||
...body,
|
...body,
|
||||||
items: body.items.map(transformCard),
|
items: body.items.map(transformCard),
|
||||||
included: {
|
included: {
|
||||||
@@ -45,26 +45,26 @@ const getCards = (boardId, data) =>
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const createCard = (boardId, data) =>
|
const createCard = (boardId, data, headers) =>
|
||||||
socket.post(`/boards/${boardId}/cards`, transformCardData(data)).then((body) => ({
|
socket.post(`/boards/${boardId}/cards`, transformCardData(data), headers).then((body) => ({
|
||||||
...body,
|
...body,
|
||||||
item: transformCard(body.item),
|
item: transformCard(body.item),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const getCard = (id) =>
|
const getCard = (id, headers) =>
|
||||||
socket.get(`/cards/${id}`).then((body) => ({
|
socket.get(`/cards/${id}`, undefined, headers).then((body) => ({
|
||||||
...body,
|
...body,
|
||||||
item: transformCard(body.item),
|
item: transformCard(body.item),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const updateCard = (id, data) =>
|
const updateCard = (id, data, headers) =>
|
||||||
socket.patch(`/cards/${id}`, transformCardData(data)).then((body) => ({
|
socket.patch(`/cards/${id}`, transformCardData(data), headers).then((body) => ({
|
||||||
...body,
|
...body,
|
||||||
item: transformCard(body.item),
|
item: transformCard(body.item),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const deleteCard = (id) =>
|
const deleteCard = (id, headers) =>
|
||||||
socket.delete(`/cards/${id}`).then((body) => ({
|
socket.delete(`/cards/${id}`, undefined, headers).then((body) => ({
|
||||||
...body,
|
...body,
|
||||||
item: transformCard(body.item),
|
item: transformCard(body.item),
|
||||||
}));
|
}));
|
||||||
@@ -78,14 +78,9 @@ const makeHandleCardCreate = (next) => (body) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const makeHandleCardUpdate = (next) => (body) => {
|
const makeHandleCardUpdate = makeHandleCardCreate;
|
||||||
next({
|
|
||||||
...body,
|
|
||||||
item: transformCard(body.item),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const makeHandleCardDelete = makeHandleCardUpdate;
|
const makeHandleCardDelete = makeHandleCardCreate;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getCards,
|
getCards,
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
import socket from './socket';
|
|
||||||
import { transformAction } from './actions';
|
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
const createCommentAction = (cardId, data) =>
|
|
||||||
socket.post(`/cards/${cardId}/comment-actions`, data).then((body) => ({
|
|
||||||
...body,
|
|
||||||
item: transformAction(body.item),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const updateCommentAction = (id, data) =>
|
|
||||||
socket.patch(`/comment-actions/${id}`, data).then((body) => ({
|
|
||||||
...body,
|
|
||||||
item: transformAction(body.item),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const deleteCommentAction = (id) =>
|
|
||||||
socket.delete(`/comment-actions/${id}`).then((body) => ({
|
|
||||||
...body,
|
|
||||||
item: transformAction(body.item),
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default {
|
|
||||||
createCommentAction,
|
|
||||||
updateCommentAction,
|
|
||||||
deleteCommentAction,
|
|
||||||
};
|
|
||||||
Executable
+28
@@ -0,0 +1,28 @@
|
|||||||
|
import socket from './socket';
|
||||||
|
import { transformActivity } from './activities';
|
||||||
|
|
||||||
|
/* Actions */
|
||||||
|
|
||||||
|
const createCommentActivity = (cardId, data, headers) =>
|
||||||
|
socket.post(`/cards/${cardId}/comment-actions`, data, headers).then((body) => ({
|
||||||
|
...body,
|
||||||
|
item: transformActivity(body.item),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const updateCommentActivity = (id, data, headers) =>
|
||||||
|
socket.patch(`/comment-actions/${id}`, data, headers).then((body) => ({
|
||||||
|
...body,
|
||||||
|
item: transformActivity(body.item),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const deleteCommentActivity = (id, headers) =>
|
||||||
|
socket.delete(`/comment-actions/${id}`, undefined, headers).then((body) => ({
|
||||||
|
...body,
|
||||||
|
item: transformActivity(body.item),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createCommentActivity,
|
||||||
|
updateCommentActivity,
|
||||||
|
deleteCommentActivity,
|
||||||
|
};
|
||||||
@@ -6,7 +6,7 @@ const http = {};
|
|||||||
|
|
||||||
// TODO: add all methods
|
// TODO: add all methods
|
||||||
['POST'].forEach((method) => {
|
['POST'].forEach((method) => {
|
||||||
http[method.toLowerCase()] = (url, data) => {
|
http[method.toLowerCase()] = (url, data, headers) => {
|
||||||
const formData = Object.keys(data).reduce((result, key) => {
|
const formData = Object.keys(data).reduce((result, key) => {
|
||||||
result.append(key, data[key]);
|
result.append(key, data[key]);
|
||||||
|
|
||||||
@@ -15,8 +15,8 @@ const http = {};
|
|||||||
|
|
||||||
return fetch(`${Config.SERVER_BASE_URL}/api${url}`, {
|
return fetch(`${Config.SERVER_BASE_URL}/api${url}`, {
|
||||||
method,
|
method,
|
||||||
|
headers,
|
||||||
body: formData,
|
body: formData,
|
||||||
...Config.FETCH_OPTIONS,
|
|
||||||
})
|
})
|
||||||
.then((response) =>
|
.then((response) =>
|
||||||
response.json().then((body) => ({
|
response.json().then((body) => ({
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import cardMemberships from './card-memberships';
|
|||||||
import cardLabels from './card-labels';
|
import cardLabels from './card-labels';
|
||||||
import tasks from './tasks';
|
import tasks from './tasks';
|
||||||
import attachments from './attachments';
|
import attachments from './attachments';
|
||||||
import actions from './actions';
|
import activities from './activities';
|
||||||
import commentActions from './comment-actions';
|
import commentActivities from './comment-activities';
|
||||||
import notifications from './notifications';
|
import notifications from './notifications';
|
||||||
|
|
||||||
export { http, socket };
|
export { http, socket };
|
||||||
@@ -33,7 +33,7 @@ export default {
|
|||||||
...cardLabels,
|
...cardLabels,
|
||||||
...tasks,
|
...tasks,
|
||||||
...attachments,
|
...attachments,
|
||||||
...actions,
|
...activities,
|
||||||
...commentActions,
|
...commentActivities,
|
||||||
...notifications,
|
...notifications,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ import socket from './socket';
|
|||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const createLabel = (boardId, data) => socket.post(`/boards/${boardId}/labels`, data);
|
const createLabel = (boardId, data, headers) =>
|
||||||
|
socket.post(`/boards/${boardId}/labels`, data, headers);
|
||||||
|
|
||||||
const updateLabel = (id, data) => socket.patch(`/labels/${id}`, data);
|
const updateLabel = (id, data, headers) => socket.patch(`/labels/${id}`, data, headers);
|
||||||
|
|
||||||
const deleteLabel = (id) => socket.delete(`/labels/${id}`);
|
const deleteLabel = (id, headers) => socket.delete(`/labels/${id}`, undefined, headers);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createLabel,
|
createLabel,
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ import socket from './socket';
|
|||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const createList = (boardId, data) => socket.post(`/boards/${boardId}/lists`, data);
|
const createList = (boardId, data, headers) =>
|
||||||
|
socket.post(`/boards/${boardId}/lists`, data, headers);
|
||||||
|
|
||||||
const updateList = (id, data) => socket.patch(`/lists/${id}`, data);
|
const updateList = (id, data, headers) => socket.patch(`/lists/${id}`, data, headers);
|
||||||
|
|
||||||
const deleteList = (id) => socket.delete(`/lists/${id}`);
|
const deleteList = (id, headers) => socket.delete(`/lists/${id}`, undefined, headers);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createList,
|
createList,
|
||||||
|
|||||||
@@ -1,33 +1,61 @@
|
|||||||
|
import omit from 'lodash/omit';
|
||||||
|
|
||||||
import socket from './socket';
|
import socket from './socket';
|
||||||
import { transformCard } from './cards';
|
import { transformCard } from './cards';
|
||||||
import { transformAction } from './actions';
|
import { transformActivity } from './activities';
|
||||||
|
|
||||||
|
/* Transformers */
|
||||||
|
|
||||||
|
export const transformNotification = (notification) => ({
|
||||||
|
...omit(notification, 'actionId'),
|
||||||
|
activityId: notification.actionId,
|
||||||
|
});
|
||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const getNotifications = () =>
|
const getNotifications = (headers) =>
|
||||||
socket.get('/notifications').then((body) => ({
|
socket.get('/notifications', undefined, headers).then((body) => ({
|
||||||
...body,
|
...body,
|
||||||
|
items: body.items.map(transformNotification),
|
||||||
included: {
|
included: {
|
||||||
...body.included,
|
...omit(body.included, 'actions'),
|
||||||
cards: body.included.cards.map(transformCard),
|
cards: body.included.cards.map(transformCard),
|
||||||
actions: body.included.actions.map(transformAction),
|
activities: body.included.actions.map(transformActivity),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const getNotification = (id) =>
|
const getNotification = (id, headers) =>
|
||||||
socket.get(`/notifications/${id}`).then((body) => ({
|
socket.get(`/notifications/${id}`, undefined, headers).then((body) => ({
|
||||||
...body,
|
...body,
|
||||||
|
item: transformNotification(body.item),
|
||||||
included: {
|
included: {
|
||||||
...body.included,
|
...omit(body.included, 'actions'),
|
||||||
cards: body.included.cards.map(transformCard),
|
cards: body.included.cards.map(transformCard),
|
||||||
actions: body.included.actions.map(transformAction),
|
activities: body.included.actions.map(transformActivity),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const updateNotifications = (ids, data) => socket.patch(`/notifications/${ids.join(',')}`, data);
|
const updateNotifications = (ids, data, headers) =>
|
||||||
|
socket.patch(`/notifications/${ids.join(',')}`, data, headers).then((body) => ({
|
||||||
|
...body,
|
||||||
|
items: body.items.map(transformNotification),
|
||||||
|
}));
|
||||||
|
|
||||||
|
/* Event handlers */
|
||||||
|
|
||||||
|
const makeHandleNotificationCreate = (next) => (body) => {
|
||||||
|
next({
|
||||||
|
...body,
|
||||||
|
item: transformNotification(body.item),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeHandleNotificationUpdate = makeHandleNotificationCreate;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getNotifications,
|
getNotifications,
|
||||||
getNotification,
|
getNotification,
|
||||||
updateNotifications,
|
updateNotifications,
|
||||||
|
makeHandleNotificationCreate,
|
||||||
|
makeHandleNotificationUpdate,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ import socket from './socket';
|
|||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const createProjectManager = (projectId, data) =>
|
const createProjectManager = (projectId, data, headers) =>
|
||||||
socket.post(`/projects/${projectId}/managers`, data);
|
socket.post(`/projects/${projectId}/managers`, data, headers);
|
||||||
|
|
||||||
const deleteProjectManager = (id) => socket.delete(`/project-managers/${id}`);
|
const deleteProjectManager = (id, headers) =>
|
||||||
|
socket.delete(`/project-managers/${id}`, undefined, headers);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createProjectManager,
|
createProjectManager,
|
||||||
|
|||||||
@@ -3,18 +3,18 @@ import socket from './socket';
|
|||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const getProjects = () => socket.get('/projects');
|
const getProjects = (headers) => socket.get('/projects', undefined, headers);
|
||||||
|
|
||||||
const createProject = (data) => socket.post('/projects', data);
|
const createProject = (data, headers) => socket.post('/projects', data, headers);
|
||||||
|
|
||||||
const getProject = (id) => socket.get(`/projects/${id}`);
|
const getProject = (id, headers) => socket.get(`/projects/${id}`, undefined, headers);
|
||||||
|
|
||||||
const updateProject = (id, data) => socket.patch(`/projects/${id}`, data);
|
const updateProject = (id, data, headers) => socket.patch(`/projects/${id}`, data, headers);
|
||||||
|
|
||||||
const updateProjectBackgroundImage = (id, data) =>
|
const updateProjectBackgroundImage = (id, data, headers) =>
|
||||||
http.post(`/projects/${id}/background-image`, data);
|
http.post(`/projects/${id}/background-image`, data, headers);
|
||||||
|
|
||||||
const deleteProject = (id) => socket.delete(`/projects/${id}`);
|
const deleteProject = (id, headers) => socket.delete(`/projects/${id}`, undefined, headers);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getProjects,
|
getProjects,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Config from '../constants/Config';
|
|||||||
|
|
||||||
const io = sailsIOClient(socketIOClient);
|
const io = sailsIOClient(socketIOClient);
|
||||||
|
|
||||||
io.sails.url = Config.SERVER_BASE_URL;
|
io.sails.url = Config.SERVER_HOST_NAME;
|
||||||
io.sails.autoConnect = false;
|
io.sails.autoConnect = false;
|
||||||
io.sails.reconnection = true;
|
io.sails.reconnection = true;
|
||||||
io.sails.useCORSRouteToGetCookie = false;
|
io.sails.useCORSRouteToGetCookie = false;
|
||||||
@@ -13,15 +13,17 @@ io.sails.environment = process.env.NODE_ENV;
|
|||||||
|
|
||||||
const { socket } = io;
|
const { socket } = io;
|
||||||
|
|
||||||
|
socket.path = `${Config.BASE_PATH}/socket.io`;
|
||||||
socket.connect = socket._connect; // eslint-disable-line no-underscore-dangle
|
socket.connect = socket._connect; // eslint-disable-line no-underscore-dangle
|
||||||
|
|
||||||
['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].forEach((method) => {
|
['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].forEach((method) => {
|
||||||
socket[method.toLowerCase()] = (url, data) =>
|
socket[method.toLowerCase()] = (url, data, headers) =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
socket.request(
|
socket.request(
|
||||||
{
|
{
|
||||||
method,
|
method,
|
||||||
data,
|
data,
|
||||||
|
headers,
|
||||||
url: `/api${url}`,
|
url: `/api${url}`,
|
||||||
},
|
},
|
||||||
(_, { body, error }) => {
|
(_, { body, error }) => {
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import socket from './socket';
|
|||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const createTask = (cardId, data) => socket.post(`/cards/${cardId}/tasks`, data);
|
const createTask = (cardId, data, headers) => socket.post(`/cards/${cardId}/tasks`, data, headers);
|
||||||
|
|
||||||
const updateTask = (id, data) => socket.patch(`/tasks/${id}`, data);
|
const updateTask = (id, data, headers) => socket.patch(`/tasks/${id}`, data, headers);
|
||||||
|
|
||||||
const deleteTask = (id) => socket.delete(`/tasks/${id}`);
|
const deleteTask = (id, headers) => socket.delete(`/tasks/${id}`, undefined, headers);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createTask,
|
createTask,
|
||||||
|
|||||||
+12
-10
@@ -3,25 +3,27 @@ import socket from './socket';
|
|||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const getUsers = () => socket.get('/users');
|
const getUsers = (headers) => socket.get('/users', undefined, headers);
|
||||||
|
|
||||||
const createUser = (data) => socket.post('/users', data);
|
const createUser = (data, headers) => socket.post('/users', data, headers);
|
||||||
|
|
||||||
const getUser = (id) => socket.get(`/users/${id}`);
|
const getUser = (id, headers) => socket.get(`/users/${id}`, undefined, headers);
|
||||||
|
|
||||||
const getCurrentUser = () => socket.get('/users/me');
|
const getCurrentUser = (headers) => socket.get('/users/me', undefined, headers);
|
||||||
|
|
||||||
const updateUser = (id, data) => socket.patch(`/users/${id}`, data);
|
const updateUser = (id, data, headers) => socket.patch(`/users/${id}`, data, headers);
|
||||||
|
|
||||||
const updateUserEmail = (id, data) => socket.patch(`/users/${id}/email`, data);
|
const updateUserEmail = (id, data, headers) => socket.patch(`/users/${id}/email`, data, headers);
|
||||||
|
|
||||||
const updateUserPassword = (id, data) => socket.patch(`/users/${id}/password`, data);
|
const updateUserPassword = (id, data, headers) =>
|
||||||
|
socket.patch(`/users/${id}/password`, data, headers);
|
||||||
|
|
||||||
const updateUserUsername = (id, data) => socket.patch(`/users/${id}/username`, data);
|
const updateUserUsername = (id, data, headers) =>
|
||||||
|
socket.patch(`/users/${id}/username`, data, headers);
|
||||||
|
|
||||||
const updateUserAvatar = (id, data) => http.post(`/users/${id}/avatar`, data);
|
const updateUserAvatar = (id, data, headers) => http.post(`/users/${id}/avatar`, data, headers);
|
||||||
|
|
||||||
const deleteUser = (id) => socket.delete(`/users/${id}`);
|
const deleteUser = (id, headers) => socket.delete(`/users/${id}`, undefined, headers);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getUsers,
|
getUsers,
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
import Filters from './Filters';
|
import Filters from './Filters';
|
||||||
import Memberships from '../Memberships';
|
import Memberships from '../Memberships';
|
||||||
|
import BoardMembershipPermissionsSelectStep from '../BoardMembershipPermissionsSelectStep';
|
||||||
|
|
||||||
import styles from './BoardActions.module.scss';
|
import styles from './BoardActions.module.scss';
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@ const BoardActions = React.memo(
|
|||||||
allUsers,
|
allUsers,
|
||||||
canEditMemberships,
|
canEditMemberships,
|
||||||
onMembershipCreate,
|
onMembershipCreate,
|
||||||
|
onMembershipUpdate,
|
||||||
onMembershipDelete,
|
onMembershipDelete,
|
||||||
onUserToFilterAdd,
|
onUserToFilterAdd,
|
||||||
onUserFromFilterRemove,
|
onUserFromFilterRemove,
|
||||||
@@ -30,8 +32,10 @@ const BoardActions = React.memo(
|
|||||||
<Memberships
|
<Memberships
|
||||||
items={memberships}
|
items={memberships}
|
||||||
allUsers={allUsers}
|
allUsers={allUsers}
|
||||||
|
permissionsSelectStep={BoardMembershipPermissionsSelectStep}
|
||||||
canEdit={canEditMemberships}
|
canEdit={canEditMemberships}
|
||||||
onCreate={onMembershipCreate}
|
onCreate={onMembershipCreate}
|
||||||
|
onUpdate={onMembershipUpdate}
|
||||||
onDelete={onMembershipDelete}
|
onDelete={onMembershipDelete}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -65,6 +69,7 @@ BoardActions.propTypes = {
|
|||||||
/* eslint-enable react/forbid-prop-types */
|
/* eslint-enable react/forbid-prop-types */
|
||||||
canEditMemberships: PropTypes.bool.isRequired,
|
canEditMemberships: PropTypes.bool.isRequired,
|
||||||
onMembershipCreate: PropTypes.func.isRequired,
|
onMembershipCreate: PropTypes.func.isRequired,
|
||||||
|
onMembershipUpdate: PropTypes.func.isRequired,
|
||||||
onMembershipDelete: PropTypes.func.isRequired,
|
onMembershipDelete: PropTypes.func.isRequired,
|
||||||
onUserToFilterAdd: PropTypes.func.isRequired,
|
onUserToFilterAdd: PropTypes.func.isRequired,
|
||||||
onUserFromFilterRemove: PropTypes.func.isRequired,
|
onUserFromFilterRemove: PropTypes.func.isRequired,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const DEFAULT_DATA = {
|
|||||||
const ListAdd = React.memo(({ onCreate, onClose }) => {
|
const ListAdd = React.memo(({ onCreate, onClose }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const [data, handleFieldChange, setData] = useForm(DEFAULT_DATA);
|
const [data, handleFieldChange, setData] = useForm(DEFAULT_DATA);
|
||||||
const [selectNameFieldState, selectNameField] = useToggle();
|
const [focusNameFieldState, focusNameField] = useToggle();
|
||||||
|
|
||||||
const nameField = useRef(null);
|
const nameField = useRef(null);
|
||||||
|
|
||||||
@@ -44,16 +44,16 @@ const ListAdd = React.memo(({ onCreate, onClose }) => {
|
|||||||
onCreate(cleanData);
|
onCreate(cleanData);
|
||||||
|
|
||||||
setData(DEFAULT_DATA);
|
setData(DEFAULT_DATA);
|
||||||
selectNameField();
|
focusNameField();
|
||||||
}, [onCreate, data, setData, selectNameField]);
|
}, [onCreate, data, setData, focusNameField]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
nameField.current.select();
|
nameField.current.focus();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useDidUpdate(() => {
|
useDidUpdate(() => {
|
||||||
nameField.current.select();
|
nameField.current.focus();
|
||||||
}, [selectNameFieldState]);
|
}, [focusNameFieldState]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form className={styles.wrapper} onSubmit={handleSubmit}>
|
<Form className={styles.wrapper} onSubmit={handleSubmit}>
|
||||||
|
|||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
import omit from 'lodash/omit';
|
||||||
|
import React, { useCallback, useState } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Button, Form, Menu, Radio, Segment } from 'semantic-ui-react';
|
||||||
|
import { Popup } from '../../lib/custom-ui';
|
||||||
|
|
||||||
|
import { BoardMembershipRoles } from '../../constants/Enums';
|
||||||
|
|
||||||
|
import styles from './BoardMembershipPermissionsSelectStep.module.scss';
|
||||||
|
|
||||||
|
const BoardMembershipPermissionsSelectStep = React.memo(
|
||||||
|
({ defaultData, title, buttonContent, onSelect, onBack }) => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
const [data, setData] = useState(() => ({
|
||||||
|
role: BoardMembershipRoles.EDITOR,
|
||||||
|
canComment: null,
|
||||||
|
...defaultData,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const handleSelectRoleClick = useCallback((role) => {
|
||||||
|
setData((prevData) => ({
|
||||||
|
...prevData,
|
||||||
|
role,
|
||||||
|
canComment: role === BoardMembershipRoles.EDITOR ? null : !!prevData.canComment,
|
||||||
|
}));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleSettingChange = useCallback((_, { name: fieldName, checked: value }) => {
|
||||||
|
setData((prevData) => ({
|
||||||
|
...prevData,
|
||||||
|
[fieldName]: value,
|
||||||
|
}));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleSubmit = useCallback(() => {
|
||||||
|
onSelect(data.role === BoardMembershipRoles.EDITOR ? omit(data, 'canComment') : data);
|
||||||
|
}, [onSelect, data]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Popup.Header onBack={onBack}>
|
||||||
|
{t(title, {
|
||||||
|
context: 'title',
|
||||||
|
})}
|
||||||
|
</Popup.Header>
|
||||||
|
<Popup.Content>
|
||||||
|
<Form onSubmit={handleSubmit}>
|
||||||
|
<Menu secondary vertical className={styles.menu}>
|
||||||
|
<Menu.Item
|
||||||
|
active={data.role === BoardMembershipRoles.EDITOR}
|
||||||
|
onClick={() => handleSelectRoleClick(BoardMembershipRoles.EDITOR)}
|
||||||
|
>
|
||||||
|
<div className={styles.menuItemTitle}>{t('common.editor')}</div>
|
||||||
|
<div className={styles.menuItemDescription}>
|
||||||
|
{t('common.canEditContentOfBoard')}
|
||||||
|
</div>
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
active={data.role === BoardMembershipRoles.VIEWER}
|
||||||
|
onClick={() => handleSelectRoleClick(BoardMembershipRoles.VIEWER)}
|
||||||
|
>
|
||||||
|
<div className={styles.menuItemTitle}>{t('common.viewer')}</div>
|
||||||
|
<div className={styles.menuItemDescription}>{t('common.canOnlyViewBoard')}</div>
|
||||||
|
</Menu.Item>
|
||||||
|
</Menu>
|
||||||
|
{data.role !== BoardMembershipRoles.EDITOR && (
|
||||||
|
<Segment basic className={styles.settings}>
|
||||||
|
<Radio
|
||||||
|
toggle
|
||||||
|
name="canComment"
|
||||||
|
checked={data.canComment}
|
||||||
|
label={t('common.canComment')}
|
||||||
|
onChange={handleSettingChange}
|
||||||
|
/>
|
||||||
|
</Segment>
|
||||||
|
)}
|
||||||
|
<Button positive content={t(buttonContent)} />
|
||||||
|
</Form>
|
||||||
|
</Popup.Content>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
BoardMembershipPermissionsSelectStep.propTypes = {
|
||||||
|
defaultData: PropTypes.object, // eslint-disable-line react/forbid-prop-types
|
||||||
|
title: PropTypes.string,
|
||||||
|
buttonContent: PropTypes.string,
|
||||||
|
onSelect: PropTypes.func.isRequired,
|
||||||
|
onBack: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
BoardMembershipPermissionsSelectStep.defaultProps = {
|
||||||
|
defaultData: undefined,
|
||||||
|
title: 'common.selectPermissions',
|
||||||
|
buttonContent: 'action.selectPermissions',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BoardMembershipPermissionsSelectStep;
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
:global(#app) {
|
||||||
|
.menu {
|
||||||
|
margin: 0 auto 8px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuItemDescription {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuItemTitle {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import BoardMembershipPermissionsSelectStep from './BoardMembershipPermissionsSelectStep';
|
||||||
|
|
||||||
|
export default BoardMembershipPermissionsSelectStep;
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Menu } from 'semantic-ui-react';
|
import { Menu } from 'semantic-ui-react';
|
||||||
import { Popup } from '../../lib/custom-ui';
|
import { Input, Popup } from '../../lib/custom-ui';
|
||||||
|
|
||||||
|
import { useField } from '../../hooks';
|
||||||
import Item from './Item';
|
import Item from './Item';
|
||||||
|
|
||||||
import styles from './BoardMembershipsStep.module.scss';
|
import styles from './BoardMembershipsStep.module.scss';
|
||||||
@@ -11,6 +12,21 @@ import styles from './BoardMembershipsStep.module.scss';
|
|||||||
const BoardMembershipsStep = React.memo(
|
const BoardMembershipsStep = React.memo(
|
||||||
({ items, currentUserIds, title, onUserSelect, onUserDeselect, onBack }) => {
|
({ items, currentUserIds, title, onUserSelect, onUserDeselect, onBack }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
const [search, handleSearchChange] = useField('');
|
||||||
|
const cleanSearch = useMemo(() => search.trim().toLowerCase(), [search]);
|
||||||
|
|
||||||
|
const filteredItems = useMemo(
|
||||||
|
() =>
|
||||||
|
items.filter(
|
||||||
|
({ user }) =>
|
||||||
|
user.email.includes(cleanSearch) ||
|
||||||
|
user.name.toLowerCase().includes(cleanSearch) ||
|
||||||
|
(user.username && user.username.includes(cleanSearch)),
|
||||||
|
),
|
||||||
|
[items, cleanSearch],
|
||||||
|
);
|
||||||
|
|
||||||
|
const searchField = useRef(null);
|
||||||
|
|
||||||
const handleUserSelect = useCallback(
|
const handleUserSelect = useCallback(
|
||||||
(id) => {
|
(id) => {
|
||||||
@@ -26,12 +42,29 @@ const BoardMembershipsStep = React.memo(
|
|||||||
[onUserDeselect],
|
[onUserDeselect],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
searchField.current.focus();
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Popup.Header onBack={onBack}>{t(title)}</Popup.Header>
|
<Popup.Header onBack={onBack}>
|
||||||
|
{t(title, {
|
||||||
|
context: 'title',
|
||||||
|
})}
|
||||||
|
</Popup.Header>
|
||||||
<Popup.Content>
|
<Popup.Content>
|
||||||
|
<Input
|
||||||
|
fluid
|
||||||
|
ref={searchField}
|
||||||
|
value={search}
|
||||||
|
placeholder={t('common.searchMembers')}
|
||||||
|
icon="search"
|
||||||
|
onChange={handleSearchChange}
|
||||||
|
/>
|
||||||
|
{filteredItems.length > 0 && (
|
||||||
<Menu secondary vertical className={styles.menu}>
|
<Menu secondary vertical className={styles.menu}>
|
||||||
{items.map((item) => (
|
{filteredItems.map((item) => (
|
||||||
<Item
|
<Item
|
||||||
key={item.id}
|
key={item.id}
|
||||||
isPersisted={item.isPersisted}
|
isPersisted={item.isPersisted}
|
||||||
@@ -42,6 +75,7 @@ const BoardMembershipsStep = React.memo(
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Menu>
|
</Menu>
|
||||||
|
)}
|
||||||
</Popup.Content>
|
</Popup.Content>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,22 @@
|
|||||||
:global(#app) {
|
:global(#app) {
|
||||||
.menu {
|
.menu {
|
||||||
margin: -7px auto -5px;
|
margin: 8px auto 0;
|
||||||
|
max-height: 320px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
scrollbar-width: thin;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
.menuItem {
|
.menuItem {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const AddStep = React.memo(({ onCreate, onClose }) => {
|
|||||||
}, [onCreate, onClose, data]);
|
}, [onCreate, onClose, data]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
nameField.current.select();
|
nameField.current.focus();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Button, Icon } from 'semantic-ui-react';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Draggable } from 'react-beautiful-dnd';
|
import { Draggable } from 'react-beautiful-dnd';
|
||||||
|
|
||||||
|
import { startTimer, stopTimer } from '../../utils/timer';
|
||||||
import Paths from '../../constants/Paths';
|
import Paths from '../../constants/Paths';
|
||||||
import Tasks from './Tasks';
|
import Tasks from './Tasks';
|
||||||
import NameEdit from './NameEdit';
|
import NameEdit from './NameEdit';
|
||||||
@@ -57,6 +58,17 @@ const Card = React.memo(
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleToggleTimerClick = useCallback(
|
||||||
|
(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
onUpdate({
|
||||||
|
timer: timer.startedAt ? stopTimer(timer) : startTimer(timer),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[timer, onUpdate],
|
||||||
|
);
|
||||||
|
|
||||||
const handleNameUpdate = useCallback(
|
const handleNameUpdate = useCallback(
|
||||||
(newName) => {
|
(newName) => {
|
||||||
onUpdate({
|
onUpdate({
|
||||||
@@ -108,7 +120,13 @@ const Card = React.memo(
|
|||||||
)}
|
)}
|
||||||
{timer && (
|
{timer && (
|
||||||
<span className={classNames(styles.attachment, styles.attachmentLeft)}>
|
<span className={classNames(styles.attachment, styles.attachmentLeft)}>
|
||||||
<Timer startedAt={timer.startedAt} total={timer.total} size="tiny" />
|
<Timer
|
||||||
|
as="span"
|
||||||
|
startedAt={timer.startedAt}
|
||||||
|
total={timer.total}
|
||||||
|
size="tiny"
|
||||||
|
onClick={canEdit ? handleToggleTimerClick : undefined}
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
@@ -148,14 +166,11 @@ const Card = React.memo(
|
|||||||
{canEdit && (
|
{canEdit && (
|
||||||
<ActionsPopup
|
<ActionsPopup
|
||||||
card={{
|
card={{
|
||||||
id,
|
|
||||||
name,
|
|
||||||
dueDate,
|
dueDate,
|
||||||
timer,
|
timer,
|
||||||
boardId,
|
boardId,
|
||||||
listId,
|
listId,
|
||||||
projectId,
|
projectId,
|
||||||
isPersisted,
|
|
||||||
}}
|
}}
|
||||||
projectsToLists={allProjectsToLists}
|
projectsToLists={allProjectsToLists}
|
||||||
boardMemberships={allBoardMemberships}
|
boardMemberships={allBoardMemberships}
|
||||||
|
|||||||
@@ -77,7 +77,10 @@
|
|||||||
|
|
||||||
.cover {
|
.cover {
|
||||||
border-radius: 3px 3px 0 0;
|
border-radius: 3px 3px 0 0;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
padding: 2px 2px 0;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.details {
|
.details {
|
||||||
@@ -114,6 +117,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
cursor: auto;
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ const NameEdit = React.forwardRef(({ children, defaultValue, onUpdate }, ref) =>
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpened) {
|
if (isOpened) {
|
||||||
field.current.ref.current.select();
|
field.current.ref.current.focus();
|
||||||
}
|
}
|
||||||
}, [isOpened]);
|
}, [isOpened]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
import React, { useCallback } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { Comment, Icon, Loader, Visibility } from 'semantic-ui-react';
|
|
||||||
|
|
||||||
import { ActionTypes } from '../../../constants/Enums';
|
|
||||||
import CommentAdd from './CommentAdd';
|
|
||||||
import Item from './Item';
|
|
||||||
|
|
||||||
import styles from './Actions.module.scss';
|
|
||||||
|
|
||||||
const Actions = React.memo(
|
|
||||||
({
|
|
||||||
items,
|
|
||||||
isFetching,
|
|
||||||
isAllFetched,
|
|
||||||
canEdit,
|
|
||||||
canEditAllComments,
|
|
||||||
onFetch,
|
|
||||||
onCommentCreate,
|
|
||||||
onCommentUpdate,
|
|
||||||
onCommentDelete,
|
|
||||||
}) => {
|
|
||||||
const [t] = useTranslation();
|
|
||||||
|
|
||||||
const handleCommentUpdate = useCallback(
|
|
||||||
(id, data) => {
|
|
||||||
onCommentUpdate(id, data);
|
|
||||||
},
|
|
||||||
[onCommentUpdate],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleCommentDelete = useCallback(
|
|
||||||
(id) => {
|
|
||||||
onCommentDelete(id);
|
|
||||||
},
|
|
||||||
[onCommentDelete],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{canEdit && (
|
|
||||||
<div className={styles.contentModule}>
|
|
||||||
<div className={styles.moduleWrapper}>
|
|
||||||
<Icon name="comment outline" className={styles.moduleIcon} />
|
|
||||||
<div className={styles.moduleHeader}>{t('common.addComment')}</div>
|
|
||||||
<CommentAdd onCreate={onCommentCreate} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className={styles.contentModule}>
|
|
||||||
<div className={styles.moduleWrapper}>
|
|
||||||
<Icon name="list ul" className={styles.moduleIcon} />
|
|
||||||
<div className={styles.moduleHeader}>{t('common.actions')}</div>
|
|
||||||
<div className={styles.wrapper}>
|
|
||||||
<Comment.Group>
|
|
||||||
{items.map((item) =>
|
|
||||||
item.type === ActionTypes.COMMENT_CARD ? (
|
|
||||||
<Item.Comment
|
|
||||||
key={item.id}
|
|
||||||
data={item.data}
|
|
||||||
createdAt={item.createdAt}
|
|
||||||
isPersisted={item.isPersisted}
|
|
||||||
user={item.user}
|
|
||||||
canEdit={(item.user.isCurrent && canEdit) || canEditAllComments}
|
|
||||||
onUpdate={(data) => handleCommentUpdate(item.id, data)}
|
|
||||||
onDelete={() => handleCommentDelete(item.id)}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<Item
|
|
||||||
key={item.id}
|
|
||||||
type={item.type}
|
|
||||||
data={item.data}
|
|
||||||
createdAt={item.createdAt}
|
|
||||||
user={item.user}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</Comment.Group>
|
|
||||||
</div>
|
|
||||||
{isFetching ? (
|
|
||||||
<Loader active inverted inline="centered" size="small" className={styles.loader} />
|
|
||||||
) : (
|
|
||||||
!isAllFetched && <Visibility fireOnMount onOnScreen={onFetch} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
Actions.propTypes = {
|
|
||||||
items: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
|
||||||
isFetching: PropTypes.bool.isRequired,
|
|
||||||
isAllFetched: PropTypes.bool.isRequired,
|
|
||||||
canEdit: PropTypes.bool.isRequired,
|
|
||||||
canEditAllComments: PropTypes.bool.isRequired,
|
|
||||||
onFetch: PropTypes.func.isRequired,
|
|
||||||
onCommentCreate: PropTypes.func.isRequired,
|
|
||||||
onCommentUpdate: PropTypes.func.isRequired,
|
|
||||||
onCommentDelete: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Actions;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import Actions from './Actions';
|
|
||||||
|
|
||||||
export default Actions;
|
|
||||||
+112
@@ -0,0 +1,112 @@
|
|||||||
|
import React, { useCallback } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Button, Comment, Icon, Loader, Visibility } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
import { ActivityTypes } from '../../../constants/Enums';
|
||||||
|
import CommentAdd from './CommentAdd';
|
||||||
|
import Item from './Item';
|
||||||
|
|
||||||
|
import styles from './Activities.module.scss';
|
||||||
|
|
||||||
|
const Activities = React.memo(
|
||||||
|
({
|
||||||
|
items,
|
||||||
|
isFetching,
|
||||||
|
isAllFetched,
|
||||||
|
isDetailsVisible,
|
||||||
|
isDetailsFetching,
|
||||||
|
canEdit,
|
||||||
|
canEditAllComments,
|
||||||
|
onFetch,
|
||||||
|
onDetailsToggle,
|
||||||
|
onCommentCreate,
|
||||||
|
onCommentUpdate,
|
||||||
|
onCommentDelete,
|
||||||
|
}) => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
const handleToggleDetailsClick = useCallback(() => {
|
||||||
|
onDetailsToggle(!isDetailsVisible);
|
||||||
|
}, [isDetailsVisible, onDetailsToggle]);
|
||||||
|
|
||||||
|
const handleCommentUpdate = useCallback(
|
||||||
|
(id, data) => {
|
||||||
|
onCommentUpdate(id, data);
|
||||||
|
},
|
||||||
|
[onCommentUpdate],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleCommentDelete = useCallback(
|
||||||
|
(id) => {
|
||||||
|
onCommentDelete(id);
|
||||||
|
},
|
||||||
|
[onCommentDelete],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.contentModule}>
|
||||||
|
<div className={styles.moduleWrapper}>
|
||||||
|
<Icon name="list ul" className={styles.moduleIcon} />
|
||||||
|
<div className={styles.moduleHeader}>
|
||||||
|
{t('common.actions')}
|
||||||
|
<Button
|
||||||
|
content={isDetailsVisible ? t('action.hideDetails') : t('action.showDetails')}
|
||||||
|
className={styles.toggleButton}
|
||||||
|
onClick={handleToggleDetailsClick}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{canEdit && <CommentAdd onCreate={onCommentCreate} />}
|
||||||
|
<div className={styles.wrapper}>
|
||||||
|
<Comment.Group>
|
||||||
|
{items.map((item) =>
|
||||||
|
item.type === ActivityTypes.COMMENT_CARD ? (
|
||||||
|
<Item.Comment
|
||||||
|
key={item.id}
|
||||||
|
data={item.data}
|
||||||
|
createdAt={item.createdAt}
|
||||||
|
isPersisted={item.isPersisted}
|
||||||
|
user={item.user}
|
||||||
|
canEdit={(item.user.isCurrent && canEdit) || canEditAllComments}
|
||||||
|
onUpdate={(data) => handleCommentUpdate(item.id, data)}
|
||||||
|
onDelete={() => handleCommentDelete(item.id)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Item
|
||||||
|
key={item.id}
|
||||||
|
type={item.type}
|
||||||
|
data={item.data}
|
||||||
|
createdAt={item.createdAt}
|
||||||
|
user={item.user}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</Comment.Group>
|
||||||
|
</div>
|
||||||
|
{isFetching || isDetailsFetching ? (
|
||||||
|
<Loader active inverted inline="centered" size="small" className={styles.loader} />
|
||||||
|
) : (
|
||||||
|
!isAllFetched && <Visibility fireOnMount onOnScreen={onFetch} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Activities.propTypes = {
|
||||||
|
items: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
|
isFetching: PropTypes.bool.isRequired,
|
||||||
|
isAllFetched: PropTypes.bool.isRequired,
|
||||||
|
isDetailsVisible: PropTypes.bool.isRequired,
|
||||||
|
isDetailsFetching: PropTypes.bool.isRequired,
|
||||||
|
canEdit: PropTypes.bool.isRequired,
|
||||||
|
canEditAllComments: PropTypes.bool.isRequired,
|
||||||
|
onFetch: PropTypes.func.isRequired,
|
||||||
|
onDetailsToggle: PropTypes.func.isRequired,
|
||||||
|
onCommentCreate: PropTypes.func.isRequired,
|
||||||
|
onCommentUpdate: PropTypes.func.isRequired,
|
||||||
|
onCommentDelete: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Activities;
|
||||||
+22
-2
@@ -8,12 +8,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.moduleHeader {
|
.moduleHeader {
|
||||||
|
align-items: center;
|
||||||
color: #17394d;
|
color: #17394d;
|
||||||
|
display: flex;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
line-height: 20px;
|
height: 36px;
|
||||||
|
justify-content: space-between;
|
||||||
margin: 0 0 4px;
|
margin: 0 0 4px;
|
||||||
padding: 8px 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.moduleIcon {
|
.moduleIcon {
|
||||||
@@ -33,6 +35,24 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.toggleButton {
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
color: #6b808c;
|
||||||
|
float: right;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-right: 0;
|
||||||
|
padding: 6px 11px;
|
||||||
|
text-align: left;
|
||||||
|
text-decoration: underline;
|
||||||
|
transition: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(9, 30, 66, 0.08);
|
||||||
|
color: #092d42;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
margin-left: -40px;
|
margin-left: -40px;
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
+32
-5
@@ -1,10 +1,11 @@
|
|||||||
import React, { useCallback, useRef } from 'react';
|
import React, { useCallback, useRef, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import TextareaAutosize from 'react-textarea-autosize';
|
import TextareaAutosize from 'react-textarea-autosize';
|
||||||
import { Button, Form, TextArea } from 'semantic-ui-react';
|
import { Button, Form, TextArea } from 'semantic-ui-react';
|
||||||
|
import { useDidUpdate, useToggle } from '../../../lib/hooks';
|
||||||
|
|
||||||
import { useForm } from '../../../hooks';
|
import { useClosableForm, useForm } from '../../../hooks';
|
||||||
|
|
||||||
import styles from './CommentAdd.module.scss';
|
import styles from './CommentAdd.module.scss';
|
||||||
|
|
||||||
@@ -14,10 +15,16 @@ const DEFAULT_DATA = {
|
|||||||
|
|
||||||
const CommentAdd = React.memo(({ onCreate }) => {
|
const CommentAdd = React.memo(({ onCreate }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
const [isOpened, setIsOpened] = useState(false);
|
||||||
const [data, handleFieldChange, setData] = useForm(DEFAULT_DATA);
|
const [data, handleFieldChange, setData] = useForm(DEFAULT_DATA);
|
||||||
|
const [selectTextFieldState, selectTextField] = useToggle();
|
||||||
|
|
||||||
const textField = useRef(null);
|
const textField = useRef(null);
|
||||||
|
|
||||||
|
const close = useCallback(() => {
|
||||||
|
setIsOpened(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const submit = useCallback(() => {
|
const submit = useCallback(() => {
|
||||||
const cleanData = {
|
const cleanData = {
|
||||||
...data,
|
...data,
|
||||||
@@ -32,7 +39,12 @@ const CommentAdd = React.memo(({ onCreate }) => {
|
|||||||
onCreate(cleanData);
|
onCreate(cleanData);
|
||||||
|
|
||||||
setData(DEFAULT_DATA);
|
setData(DEFAULT_DATA);
|
||||||
}, [onCreate, data, setData]);
|
selectTextField();
|
||||||
|
}, [onCreate, data, setData, selectTextField]);
|
||||||
|
|
||||||
|
const handleFieldFocus = useCallback(() => {
|
||||||
|
setIsOpened(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleFieldKeyDown = useCallback(
|
const handleFieldKeyDown = useCallback(
|
||||||
(event) => {
|
(event) => {
|
||||||
@@ -43,10 +55,16 @@ const CommentAdd = React.memo(({ onCreate }) => {
|
|||||||
[submit],
|
[submit],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [handleFieldBlur, handleControlMouseOver, handleControlMouseOut] = useClosableForm(close);
|
||||||
|
|
||||||
const handleSubmit = useCallback(() => {
|
const handleSubmit = useCallback(() => {
|
||||||
submit();
|
submit();
|
||||||
}, [submit]);
|
}, [submit]);
|
||||||
|
|
||||||
|
useDidUpdate(() => {
|
||||||
|
textField.current.ref.current.focus();
|
||||||
|
}, [selectTextFieldState]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form onSubmit={handleSubmit}>
|
<Form onSubmit={handleSubmit}>
|
||||||
<TextArea
|
<TextArea
|
||||||
@@ -55,15 +73,24 @@ const CommentAdd = React.memo(({ onCreate }) => {
|
|||||||
name="text"
|
name="text"
|
||||||
value={data.text}
|
value={data.text}
|
||||||
placeholder={t('common.writeComment')}
|
placeholder={t('common.writeComment')}
|
||||||
minRows={3}
|
minRows={isOpened ? 3 : 1}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
className={styles.field}
|
className={styles.field}
|
||||||
|
onFocus={handleFieldFocus}
|
||||||
onKeyDown={handleFieldKeyDown}
|
onKeyDown={handleFieldKeyDown}
|
||||||
onChange={handleFieldChange}
|
onChange={handleFieldChange}
|
||||||
|
onBlur={handleFieldBlur}
|
||||||
/>
|
/>
|
||||||
|
{isOpened && (
|
||||||
<div className={styles.controls}>
|
<div className={styles.controls}>
|
||||||
<Button positive content={t('action.addComment')} disabled={!data.text} />
|
<Button
|
||||||
|
positive
|
||||||
|
content={t('action.addComment')}
|
||||||
|
onMouseOver={handleControlMouseOver}
|
||||||
|
onMouseOut={handleControlMouseOut}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
+1
-1
@@ -76,7 +76,7 @@ const CommentEdit = React.forwardRef(({ children, defaultData, onUpdate }, ref)
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpened) {
|
if (isOpened) {
|
||||||
textField.current.ref.current.select();
|
textField.current.ref.current.focus();
|
||||||
}
|
}
|
||||||
}, [isOpened]);
|
}, [isOpened]);
|
||||||
|
|
||||||
+3
-3
@@ -4,7 +4,7 @@ import classNames from 'classnames';
|
|||||||
import { useTranslation, Trans } from 'react-i18next';
|
import { useTranslation, Trans } from 'react-i18next';
|
||||||
import { Comment } from 'semantic-ui-react';
|
import { Comment } from 'semantic-ui-react';
|
||||||
|
|
||||||
import { ActionTypes } from '../../../constants/Enums';
|
import { ActivityTypes } from '../../../constants/Enums';
|
||||||
import ItemComment from './ItemComment';
|
import ItemComment from './ItemComment';
|
||||||
import User from '../../User';
|
import User from '../../User';
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ const Item = React.memo(({ type, data, createdAt, user }) => {
|
|||||||
let contentNode;
|
let contentNode;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ActionTypes.CREATE_CARD:
|
case ActivityTypes.CREATE_CARD:
|
||||||
contentNode = (
|
contentNode = (
|
||||||
<Trans
|
<Trans
|
||||||
i18nKey="common.userAddedThisCardToList"
|
i18nKey="common.userAddedThisCardToList"
|
||||||
@@ -34,7 +34,7 @@ const Item = React.memo(({ type, data, createdAt, user }) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ActionTypes.MOVE_CARD:
|
case ActivityTypes.MOVE_CARD:
|
||||||
contentNode = (
|
contentNode = (
|
||||||
<Trans
|
<Trans
|
||||||
i18nKey="common.userMovedThisCardFromListToList"
|
i18nKey="common.userMovedThisCardFromListToList"
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
import Activities from './Activities';
|
||||||
|
|
||||||
|
export default Activities;
|
||||||
@@ -37,7 +37,7 @@ const TextFileAddModal = React.memo(({ content, onCreate, onClose }) => {
|
|||||||
}, [content, onCreate, onClose, data]);
|
}, [content, onCreate, onClose, data]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
nameField.current.select();
|
nameField.current.focus();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import styles from './Attachments.module.scss';
|
|||||||
const INITIALLY_VISIBLE = 4;
|
const INITIALLY_VISIBLE = 4;
|
||||||
|
|
||||||
const Attachments = React.memo(
|
const Attachments = React.memo(
|
||||||
({ items, onUpdate, onDelete, onCoverUpdate, onGalleryOpen, onGalleryClose }) => {
|
({ items, canEdit, onUpdate, onDelete, onCoverUpdate, onGalleryOpen, onGalleryClose }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const [isAllVisible, toggleAllVisible] = useToggle();
|
const [isAllVisible, toggleAllVisible] = useToggle();
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ const Attachments = React.memo(
|
|||||||
}, [toggleAllVisible]);
|
}, [toggleAllVisible]);
|
||||||
|
|
||||||
const galleryItemsNode = items.map((item, index) => {
|
const galleryItemsNode = items.map((item, index) => {
|
||||||
const isPdf = item.url.endsWith('.pdf');
|
const isPdf = item.url && item.url.endsWith('.pdf');
|
||||||
|
|
||||||
let props;
|
let props;
|
||||||
if (item.image) {
|
if (item.image) {
|
||||||
@@ -99,6 +99,7 @@ const Attachments = React.memo(
|
|||||||
createdAt={item.createdAt}
|
createdAt={item.createdAt}
|
||||||
isCover={item.isCover}
|
isCover={item.isCover}
|
||||||
isPersisted={item.isPersisted}
|
isPersisted={item.isPersisted}
|
||||||
|
canEdit={canEdit}
|
||||||
onClick={item.image || isPdf ? open : undefined}
|
onClick={item.image || isPdf ? open : undefined}
|
||||||
onCoverSelect={() => handleCoverSelect(item.id)}
|
onCoverSelect={() => handleCoverSelect(item.id)}
|
||||||
onCoverDeselect={handleCoverDeselect}
|
onCoverDeselect={handleCoverDeselect}
|
||||||
@@ -151,6 +152,7 @@ const Attachments = React.memo(
|
|||||||
|
|
||||||
Attachments.propTypes = {
|
Attachments.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,
|
||||||
onUpdate: PropTypes.func.isRequired,
|
onUpdate: PropTypes.func.isRequired,
|
||||||
onDelete: PropTypes.func.isRequired,
|
onDelete: PropTypes.func.isRequired,
|
||||||
onCoverUpdate: PropTypes.func.isRequired,
|
onCoverUpdate: PropTypes.func.isRequired,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const Item = React.forwardRef(
|
|||||||
createdAt,
|
createdAt,
|
||||||
isCover,
|
isCover,
|
||||||
isPersisted,
|
isPersisted,
|
||||||
|
canEdit,
|
||||||
onCoverSelect,
|
onCoverSelect,
|
||||||
onCoverDeselect,
|
onCoverDeselect,
|
||||||
onClick,
|
onClick,
|
||||||
@@ -96,7 +97,7 @@ const Item = React.forwardRef(
|
|||||||
value: createdAt,
|
value: createdAt,
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
{coverUrl && (
|
{coverUrl && canEdit && (
|
||||||
<span className={styles.options}>
|
<span className={styles.options}>
|
||||||
<button type="button" className={styles.option} onClick={handleToggleCoverClick}>
|
<button type="button" className={styles.option} onClick={handleToggleCoverClick}>
|
||||||
<Icon
|
<Icon
|
||||||
@@ -118,6 +119,7 @@ const Item = React.forwardRef(
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{canEdit && (
|
||||||
<EditPopup
|
<EditPopup
|
||||||
defaultData={{
|
defaultData={{
|
||||||
name,
|
name,
|
||||||
@@ -129,6 +131,7 @@ const Item = React.forwardRef(
|
|||||||
<Icon fitted name="pencil" size="small" />
|
<Icon fitted name="pencil" size="small" />
|
||||||
</Button>
|
</Button>
|
||||||
</EditPopup>
|
</EditPopup>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -141,6 +144,7 @@ Item.propTypes = {
|
|||||||
createdAt: PropTypes.instanceOf(Date),
|
createdAt: PropTypes.instanceOf(Date),
|
||||||
isCover: PropTypes.bool.isRequired,
|
isCover: PropTypes.bool.isRequired,
|
||||||
isPersisted: PropTypes.bool.isRequired,
|
isPersisted: PropTypes.bool.isRequired,
|
||||||
|
canEdit: PropTypes.bool.isRequired,
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
onCoverSelect: PropTypes.func.isRequired,
|
onCoverSelect: PropTypes.func.isRequired,
|
||||||
onCoverDeselect: PropTypes.func.isRequired,
|
onCoverDeselect: PropTypes.func.isRequired,
|
||||||
|
|||||||
@@ -5,13 +5,14 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { Button, Grid, Icon, Modal } from 'semantic-ui-react';
|
import { Button, Grid, Icon, Modal } from 'semantic-ui-react';
|
||||||
import { Markdown } from '../../lib/custom-ui';
|
import { Markdown } from '../../lib/custom-ui';
|
||||||
|
|
||||||
|
import { startTimer, stopTimer } from '../../utils/timer';
|
||||||
import NameField from './NameField';
|
import NameField from './NameField';
|
||||||
import DescriptionEdit from './DescriptionEdit';
|
import DescriptionEdit from './DescriptionEdit';
|
||||||
import Tasks from './Tasks';
|
import Tasks from './Tasks';
|
||||||
import Attachments from './Attachments';
|
import Attachments from './Attachments';
|
||||||
import AttachmentAddZone from './AttachmentAddZone';
|
import AttachmentAddZone from './AttachmentAddZone';
|
||||||
import AttachmentAddPopup from './AttachmentAddPopup';
|
import AttachmentAddPopup from './AttachmentAddPopup';
|
||||||
import Actions from './Actions';
|
import Activities from './Activities';
|
||||||
import User from '../User';
|
import User from '../User';
|
||||||
import Label from '../Label';
|
import Label from '../Label';
|
||||||
import DueDate from '../DueDate';
|
import DueDate from '../DueDate';
|
||||||
@@ -32,8 +33,10 @@ const CardModal = React.memo(
|
|||||||
dueDate,
|
dueDate,
|
||||||
timer,
|
timer,
|
||||||
isSubscribed,
|
isSubscribed,
|
||||||
isActionsFetching,
|
isActivitiesFetching,
|
||||||
isAllActionsFetched,
|
isAllActivitiesFetched,
|
||||||
|
isActivitiesDetailsVisible,
|
||||||
|
isActivitiesDetailsFetching,
|
||||||
listId,
|
listId,
|
||||||
boardId,
|
boardId,
|
||||||
projectId,
|
projectId,
|
||||||
@@ -41,12 +44,13 @@ const CardModal = React.memo(
|
|||||||
labels,
|
labels,
|
||||||
tasks,
|
tasks,
|
||||||
attachments,
|
attachments,
|
||||||
actions,
|
activities,
|
||||||
allProjectsToLists,
|
allProjectsToLists,
|
||||||
allBoardMemberships,
|
allBoardMemberships,
|
||||||
allLabels,
|
allLabels,
|
||||||
canEdit,
|
canEdit,
|
||||||
canEditAllCommentActions,
|
canEditCommentActivities,
|
||||||
|
canEditAllCommentActivities,
|
||||||
onUpdate,
|
onUpdate,
|
||||||
onMove,
|
onMove,
|
||||||
onTransfer,
|
onTransfer,
|
||||||
@@ -61,20 +65,28 @@ const CardModal = React.memo(
|
|||||||
onLabelDelete,
|
onLabelDelete,
|
||||||
onTaskCreate,
|
onTaskCreate,
|
||||||
onTaskUpdate,
|
onTaskUpdate,
|
||||||
|
onTaskMove,
|
||||||
onTaskDelete,
|
onTaskDelete,
|
||||||
onAttachmentCreate,
|
onAttachmentCreate,
|
||||||
onAttachmentUpdate,
|
onAttachmentUpdate,
|
||||||
onAttachmentDelete,
|
onAttachmentDelete,
|
||||||
onActionsFetch,
|
onActivitiesFetch,
|
||||||
onCommentActionCreate,
|
onActivitiesDetailsToggle,
|
||||||
onCommentActionUpdate,
|
onCommentActivityCreate,
|
||||||
onCommentActionDelete,
|
onCommentActivityUpdate,
|
||||||
|
onCommentActivityDelete,
|
||||||
onClose,
|
onClose,
|
||||||
}) => {
|
}) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
const isGalleryOpened = useRef(false);
|
const isGalleryOpened = useRef(false);
|
||||||
|
|
||||||
|
const handleToggleTimerClick = useCallback(() => {
|
||||||
|
onUpdate({
|
||||||
|
timer: timer.startedAt ? stopTimer(timer) : startTimer(timer),
|
||||||
|
});
|
||||||
|
}, [timer, onUpdate]);
|
||||||
|
|
||||||
const handleNameUpdate = useCallback(
|
const handleNameUpdate = useCallback(
|
||||||
(newName) => {
|
(newName) => {
|
||||||
onUpdate({
|
onUpdate({
|
||||||
@@ -286,6 +298,19 @@ const CardModal = React.memo(
|
|||||||
<Timer startedAt={timer.startedAt} total={timer.total} />
|
<Timer startedAt={timer.startedAt} total={timer.total} />
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
|
{canEdit && (
|
||||||
|
<button
|
||||||
|
onClick={handleToggleTimerClick}
|
||||||
|
type="button"
|
||||||
|
className={classNames(styles.attachment, styles.dueDate)}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name={timer.startedAt ? 'pause' : 'play'}
|
||||||
|
size="small"
|
||||||
|
className={styles.addAttachment}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -298,7 +323,10 @@ const CardModal = React.memo(
|
|||||||
{canEdit ? (
|
{canEdit ? (
|
||||||
<DescriptionEdit defaultValue={description} onUpdate={handleDescriptionUpdate}>
|
<DescriptionEdit defaultValue={description} onUpdate={handleDescriptionUpdate}>
|
||||||
{description ? (
|
{description ? (
|
||||||
<button type="button" className={styles.descriptionText}>
|
<button
|
||||||
|
type="button"
|
||||||
|
className={classNames(styles.descriptionText, styles.cursorPointer)}
|
||||||
|
>
|
||||||
<Markdown linkStopPropagation linkTarget="_blank">
|
<Markdown linkStopPropagation linkTarget="_blank">
|
||||||
{description}
|
{description}
|
||||||
</Markdown>
|
</Markdown>
|
||||||
@@ -331,6 +359,7 @@ const CardModal = React.memo(
|
|||||||
canEdit={canEdit}
|
canEdit={canEdit}
|
||||||
onCreate={onTaskCreate}
|
onCreate={onTaskCreate}
|
||||||
onUpdate={onTaskUpdate}
|
onUpdate={onTaskUpdate}
|
||||||
|
onMove={onTaskMove}
|
||||||
onDelete={onTaskDelete}
|
onDelete={onTaskDelete}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -343,6 +372,7 @@ const CardModal = React.memo(
|
|||||||
<div className={styles.moduleHeader}>{t('common.attachments')}</div>
|
<div className={styles.moduleHeader}>{t('common.attachments')}</div>
|
||||||
<Attachments
|
<Attachments
|
||||||
items={attachments}
|
items={attachments}
|
||||||
|
canEdit={canEdit}
|
||||||
onUpdate={onAttachmentUpdate}
|
onUpdate={onAttachmentUpdate}
|
||||||
onDelete={onAttachmentDelete}
|
onDelete={onAttachmentDelete}
|
||||||
onCoverUpdate={handleCoverUpdate}
|
onCoverUpdate={handleCoverUpdate}
|
||||||
@@ -352,16 +382,19 @@ const CardModal = React.memo(
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Actions
|
<Activities
|
||||||
items={actions}
|
items={activities}
|
||||||
isFetching={isActionsFetching}
|
isFetching={isActivitiesFetching}
|
||||||
isAllFetched={isAllActionsFetched}
|
isAllFetched={isAllActivitiesFetched}
|
||||||
canEdit={canEdit}
|
isDetailsVisible={isActivitiesDetailsVisible}
|
||||||
canEditAllComments={canEditAllCommentActions}
|
isDetailsFetching={isActivitiesDetailsFetching}
|
||||||
onFetch={onActionsFetch}
|
canEdit={canEditCommentActivities}
|
||||||
onCommentCreate={onCommentActionCreate}
|
canEditAllComments={canEditAllCommentActivities}
|
||||||
onCommentUpdate={onCommentActionUpdate}
|
onFetch={onActivitiesFetch}
|
||||||
onCommentDelete={onCommentActionDelete}
|
onDetailsToggle={onActivitiesDetailsToggle}
|
||||||
|
onCommentCreate={onCommentActivityCreate}
|
||||||
|
onCommentUpdate={onCommentActivityUpdate}
|
||||||
|
onCommentDelete={onCommentActivityDelete}
|
||||||
/>
|
/>
|
||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
{canEdit && (
|
{canEdit && (
|
||||||
@@ -465,7 +498,7 @@ const CardModal = React.memo(
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open closeIcon size="small" centered={false} onClose={handleClose}>
|
<Modal open closeIcon centered={false} onClose={handleClose} className={styles.wrapper}>
|
||||||
{canEdit ? (
|
{canEdit ? (
|
||||||
<AttachmentAddZone onCreate={onAttachmentCreate}>{contentNode}</AttachmentAddZone>
|
<AttachmentAddZone onCreate={onAttachmentCreate}>{contentNode}</AttachmentAddZone>
|
||||||
) : (
|
) : (
|
||||||
@@ -482,8 +515,10 @@ CardModal.propTypes = {
|
|||||||
dueDate: PropTypes.instanceOf(Date),
|
dueDate: PropTypes.instanceOf(Date),
|
||||||
timer: PropTypes.object, // eslint-disable-line react/forbid-prop-types
|
timer: PropTypes.object, // eslint-disable-line react/forbid-prop-types
|
||||||
isSubscribed: PropTypes.bool.isRequired,
|
isSubscribed: PropTypes.bool.isRequired,
|
||||||
isActionsFetching: PropTypes.bool.isRequired,
|
isActivitiesFetching: PropTypes.bool.isRequired,
|
||||||
isAllActionsFetched: PropTypes.bool.isRequired,
|
isAllActivitiesFetched: PropTypes.bool.isRequired,
|
||||||
|
isActivitiesDetailsVisible: PropTypes.bool.isRequired,
|
||||||
|
isActivitiesDetailsFetching: PropTypes.bool.isRequired,
|
||||||
listId: PropTypes.string.isRequired,
|
listId: PropTypes.string.isRequired,
|
||||||
boardId: PropTypes.string.isRequired,
|
boardId: PropTypes.string.isRequired,
|
||||||
projectId: PropTypes.string.isRequired,
|
projectId: PropTypes.string.isRequired,
|
||||||
@@ -492,13 +527,14 @@ CardModal.propTypes = {
|
|||||||
labels: PropTypes.array.isRequired,
|
labels: PropTypes.array.isRequired,
|
||||||
tasks: PropTypes.array.isRequired,
|
tasks: PropTypes.array.isRequired,
|
||||||
attachments: PropTypes.array.isRequired,
|
attachments: PropTypes.array.isRequired,
|
||||||
actions: PropTypes.array.isRequired,
|
activities: PropTypes.array.isRequired,
|
||||||
allProjectsToLists: PropTypes.array.isRequired,
|
allProjectsToLists: PropTypes.array.isRequired,
|
||||||
allBoardMemberships: 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,
|
canEdit: PropTypes.bool.isRequired,
|
||||||
canEditAllCommentActions: PropTypes.bool.isRequired,
|
canEditCommentActivities: PropTypes.bool.isRequired,
|
||||||
|
canEditAllCommentActivities: 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,
|
||||||
@@ -513,14 +549,16 @@ CardModal.propTypes = {
|
|||||||
onLabelDelete: PropTypes.func.isRequired,
|
onLabelDelete: PropTypes.func.isRequired,
|
||||||
onTaskCreate: PropTypes.func.isRequired,
|
onTaskCreate: PropTypes.func.isRequired,
|
||||||
onTaskUpdate: PropTypes.func.isRequired,
|
onTaskUpdate: PropTypes.func.isRequired,
|
||||||
|
onTaskMove: PropTypes.func.isRequired,
|
||||||
onTaskDelete: PropTypes.func.isRequired,
|
onTaskDelete: PropTypes.func.isRequired,
|
||||||
onAttachmentCreate: PropTypes.func.isRequired,
|
onAttachmentCreate: PropTypes.func.isRequired,
|
||||||
onAttachmentUpdate: PropTypes.func.isRequired,
|
onAttachmentUpdate: PropTypes.func.isRequired,
|
||||||
onAttachmentDelete: PropTypes.func.isRequired,
|
onAttachmentDelete: PropTypes.func.isRequired,
|
||||||
onActionsFetch: PropTypes.func.isRequired,
|
onActivitiesFetch: PropTypes.func.isRequired,
|
||||||
onCommentActionCreate: PropTypes.func.isRequired,
|
onActivitiesDetailsToggle: PropTypes.func.isRequired,
|
||||||
onCommentActionUpdate: PropTypes.func.isRequired,
|
onCommentActivityCreate: PropTypes.func.isRequired,
|
||||||
onCommentActionDelete: PropTypes.func.isRequired,
|
onCommentActivityUpdate: PropTypes.func.isRequired,
|
||||||
|
onCommentActivityDelete: PropTypes.func.isRequired,
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,10 @@
|
|||||||
padding: 8px 8px 0 16px;
|
padding: 8px 8px 0 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cursorPointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.dueDate {
|
.dueDate {
|
||||||
background: rgba(9, 30, 66, 0.04);
|
background: rgba(9, 30, 66, 0.04);
|
||||||
border: none;
|
border: none;
|
||||||
@@ -114,7 +118,6 @@
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
color: #17394d;
|
color: #17394d;
|
||||||
cursor: pointer;
|
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -193,4 +196,14 @@
|
|||||||
margin: 0 8px 4px 0;
|
margin: 0 8px 4px 0;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
width: 880px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 926px) {
|
||||||
|
.wrapper {
|
||||||
|
width: 95%;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ const DescriptionEdit = React.forwardRef(({ children, defaultValue, onUpdate },
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpened) {
|
if (isOpened) {
|
||||||
field.current.ref.current.select();
|
field.current.ref.current.focus();
|
||||||
}
|
}
|
||||||
}, [isOpened]);
|
}, [isOpened]);
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const Add = React.forwardRef(({ children, onCreate }, ref) => {
|
|||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const [isOpened, setIsOpened] = useState(false);
|
const [isOpened, setIsOpened] = useState(false);
|
||||||
const [data, handleFieldChange, setData] = useForm(DEFAULT_DATA);
|
const [data, handleFieldChange, setData] = useForm(DEFAULT_DATA);
|
||||||
const [selectNameFieldState, selectNameField] = useToggle();
|
const [focusNameFieldState, focusNameField] = useToggle();
|
||||||
|
|
||||||
const nameField = useRef(null);
|
const nameField = useRef(null);
|
||||||
|
|
||||||
@@ -43,8 +43,8 @@ const Add = React.forwardRef(({ children, onCreate }, ref) => {
|
|||||||
onCreate(cleanData);
|
onCreate(cleanData);
|
||||||
|
|
||||||
setData(DEFAULT_DATA);
|
setData(DEFAULT_DATA);
|
||||||
selectNameField();
|
focusNameField();
|
||||||
}, [onCreate, data, setData, selectNameField]);
|
}, [onCreate, data, setData, focusNameField]);
|
||||||
|
|
||||||
useImperativeHandle(
|
useImperativeHandle(
|
||||||
ref,
|
ref,
|
||||||
@@ -81,13 +81,13 @@ const Add = React.forwardRef(({ children, onCreate }, ref) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpened) {
|
if (isOpened) {
|
||||||
nameField.current.ref.current.select();
|
nameField.current.ref.current.focus();
|
||||||
}
|
}
|
||||||
}, [isOpened]);
|
}, [isOpened]);
|
||||||
|
|
||||||
useDidUpdate(() => {
|
useDidUpdate(() => {
|
||||||
nameField.current.ref.current.select();
|
nameField.current.ref.current.focus();
|
||||||
}, [selectNameFieldState]);
|
}, [focusNameFieldState]);
|
||||||
|
|
||||||
if (!isOpened) {
|
if (!isOpened) {
|
||||||
return React.cloneElement(children, {
|
return React.cloneElement(children, {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import React, { useCallback, useRef } from 'react';
|
import React, { useCallback, useRef } from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { Draggable } from 'react-beautiful-dnd';
|
||||||
import { Button, Checkbox, Icon } from 'semantic-ui-react';
|
import { Button, Checkbox, Icon } from 'semantic-ui-react';
|
||||||
|
|
||||||
import NameEdit from './NameEdit';
|
import NameEdit from './NameEdit';
|
||||||
@@ -8,7 +10,8 @@ import ActionsPopup from './ActionsPopup';
|
|||||||
|
|
||||||
import styles from './Item.module.scss';
|
import styles from './Item.module.scss';
|
||||||
|
|
||||||
const Item = React.memo(({ name, isCompleted, isPersisted, canEdit, onUpdate, onDelete }) => {
|
const Item = React.memo(
|
||||||
|
({ id, index, name, isCompleted, isPersisted, canEdit, onUpdate, onDelete }) => {
|
||||||
const nameEdit = useRef(null);
|
const nameEdit = useRef(null);
|
||||||
|
|
||||||
const handleClick = useCallback(() => {
|
const handleClick = useCallback(() => {
|
||||||
@@ -37,7 +40,11 @@ const Item = React.memo(({ name, isCompleted, isPersisted, canEdit, onUpdate, on
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.wrapper}>
|
<Draggable draggableId={id} index={index} isDragDisabled={!isPersisted || !canEdit}>
|
||||||
|
{({ innerRef, draggableProps, dragHandleProps }, { isDragging }) => {
|
||||||
|
const contentNode = (
|
||||||
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
|
<div {...draggableProps} {...dragHandleProps} ref={innerRef} className={styles.wrapper}>
|
||||||
<span className={styles.checkboxWrapper}>
|
<span className={styles.checkboxWrapper}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={isCompleted}
|
checked={isCompleted}
|
||||||
@@ -71,9 +78,17 @@ const Item = React.memo(({ name, isCompleted, isPersisted, canEdit, onUpdate, on
|
|||||||
</NameEdit>
|
</NameEdit>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
return isDragging ? ReactDOM.createPortal(contentNode, document.body) : contentNode;
|
||||||
|
}}
|
||||||
|
</Draggable>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
Item.propTypes = {
|
Item.propTypes = {
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
index: PropTypes.number.isRequired,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
isCompleted: PropTypes.bool.isRequired,
|
isCompleted: PropTypes.bool.isRequired,
|
||||||
isPersisted: PropTypes.bool.isRequired,
|
isPersisted: PropTypes.bool.isRequired,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user