diff --git a/client/src/components/UserSettingsModal/PreferencesPane.jsx b/client/src/components/UserSettingsModal/PreferencesPane.jsx
new file mode 100644
index 00000000..1a4d5495
--- /dev/null
+++ b/client/src/components/UserSettingsModal/PreferencesPane.jsx
@@ -0,0 +1,34 @@
+import React, { useCallback } from 'react';
+import PropTypes from 'prop-types';
+import { useTranslation } from 'react-i18next';
+import { Radio, Tab } from 'semantic-ui-react';
+
+import styles from './PreferencesPane.module.css';
+
+const PreferencesPane = React.memo(({ subscribeToOwnCards, onUpdate }) => {
+ const [t] = useTranslation();
+
+ const handleSubscribeToOwnCardsChange = useCallback(() => {
+ onUpdate({
+ subscribeToOwnCards: !subscribeToOwnCards,
+ });
+ }, [subscribeToOwnCards, onUpdate]);
+
+ return (
+
+
+
+ );
+});
+
+PreferencesPane.propTypes = {
+ subscribeToOwnCards: PropTypes.bool.isRequired,
+ onUpdate: PropTypes.func.isRequired,
+};
+
+export default PreferencesPane;
diff --git a/client/src/components/UserSettingsModal/PreferencesPane.module.css b/client/src/components/UserSettingsModal/PreferencesPane.module.css
new file mode 100644
index 00000000..cbc2be9f
--- /dev/null
+++ b/client/src/components/UserSettingsModal/PreferencesPane.module.css
@@ -0,0 +1,4 @@
+.wrapper {
+ border: none !important;
+ box-shadow: none !important;
+}
diff --git a/client/src/components/UserSettingsModal/UserSettingsModal.jsx b/client/src/components/UserSettingsModal/UserSettingsModal.jsx
index eb1d5ec0..feb44383 100644
--- a/client/src/components/UserSettingsModal/UserSettingsModal.jsx
+++ b/client/src/components/UserSettingsModal/UserSettingsModal.jsx
@@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
import { Modal, Tab } from 'semantic-ui-react';
import AccountPane from './AccountPane';
+import PreferencesPane from './PreferencesPane';
const UserSettingsModal = React.memo(
({
@@ -13,6 +14,7 @@ const UserSettingsModal = React.memo(
avatar,
phone,
organization,
+ subscribeToOwnCards,
isAvatarUploading,
usernameUpdateForm,
emailUpdateForm,
@@ -57,12 +59,26 @@ const UserSettingsModal = React.memo(
/>
),
},
+ {
+ menuItem: t('common.preferences', {
+ context: 'title',
+ }),
+ render: () => (
+
+ ),
+ },
];
return (
-
+
);
@@ -76,6 +92,7 @@ UserSettingsModal.propTypes = {
avatar: PropTypes.string,
phone: PropTypes.string,
organization: PropTypes.string,
+ subscribeToOwnCards: PropTypes.bool.isRequired,
isAvatarUploading: PropTypes.bool.isRequired,
/* eslint-disable react/forbid-prop-types */
usernameUpdateForm: PropTypes.object.isRequired,
diff --git a/client/src/containers/UserSettingsModalContainer.js b/client/src/containers/UserSettingsModalContainer.js
index 38ebae7b..9480e8a9 100644
--- a/client/src/containers/UserSettingsModalContainer.js
+++ b/client/src/containers/UserSettingsModalContainer.js
@@ -23,6 +23,7 @@ const mapStateToProps = (state) => {
avatar,
phone,
organization,
+ subscribeToOwnCards,
isAvatarUploading,
emailUpdateForm,
passwordUpdateForm,
@@ -36,6 +37,7 @@ const mapStateToProps = (state) => {
avatar,
phone,
organization,
+ subscribeToOwnCards,
isAvatarUploading,
emailUpdateForm,
passwordUpdateForm,
diff --git a/client/src/locales/en-US/app.js b/client/src/locales/en-US/app.js
index 14d39522..b0d8ac62 100644
--- a/client/src/locales/en-US/app.js
+++ b/client/src/locales/en-US/app.js
@@ -86,12 +86,14 @@ export default {
optional_inline: 'optional',
organization: 'Organization',
phone: 'Phone',
+ preferences: 'Preferences',
projectNotFound_title: 'Project Not Found',
refreshPageToLoadLastDataAndReceiveUpdates:
'<0>Refresh the page0> to load last data
and receive updates',
removeMember_title: 'Remove Member',
seconds: 'Seconds',
settings: 'Settings',
+ subscribeToMyOwnCardsByDefault: 'Subscribe to my own cards by default',
taskActions_title: 'Task Actions',
tasks: 'Tasks',
time: 'Time',
diff --git a/client/src/locales/ru-RU/app.js b/client/src/locales/ru-RU/app.js
index a2c1258a..3fd9dd19 100644
--- a/client/src/locales/ru-RU/app.js
+++ b/client/src/locales/ru-RU/app.js
@@ -90,12 +90,14 @@ export default {
optional_inline: 'необязательно',
organization: 'Организация',
phone: 'Телефон',
+ preferences: 'Предпочтения',
projectNotFound: 'Доска не найдена',
refreshPageToLoadLastDataAndReceiveUpdates:
'<0>Обновите страницу0>, чтобы загрузить
актуальные данные и получать обновления',
removeMember: 'Удаление участника',
seconds: 'Секунды',
settings: 'Настройки',
+ subscribeToMyOwnCardsByDefault: 'По умолчанию подписаться на мои собственные карточки',
taskActions: 'Действия с задачей',
tasks: 'Задачи',
time: 'Время',
diff --git a/client/src/models/User.js b/client/src/models/User.js
index 8a73a289..9ebfe636 100755
--- a/client/src/models/User.js
+++ b/client/src/models/User.js
@@ -39,6 +39,7 @@ export default class extends Model {
avatar: attr(),
phone: attr(),
organization: attr(),
+ subscribeToOwnCards: attr(),
deletedAt: attr(),
isAdmin: attr({
getDefault: () => false,
diff --git a/server/api/controllers/users/create.js b/server/api/controllers/users/create.js
index f7cd9876..8cdf3ce2 100755
--- a/server/api/controllers/users/create.js
+++ b/server/api/controllers/users/create.js
@@ -40,6 +40,9 @@ module.exports = {
isNotEmptyString: true,
allowNull: true,
},
+ subscribeToOwnCards: {
+ type: 'boolean',
+ },
},
exits: {
@@ -59,6 +62,7 @@ module.exports = {
'username',
'phone',
'organization',
+ 'subscribeToOwnCards',
]);
const user = await sails.helpers
diff --git a/server/api/controllers/users/update.js b/server/api/controllers/users/update.js
index d6099f24..3447b709 100755
--- a/server/api/controllers/users/update.js
+++ b/server/api/controllers/users/update.js
@@ -32,6 +32,9 @@ module.exports = {
isNotEmptyString: true,
allowNull: true,
},
+ subscribeToOwnCards: {
+ type: 'boolean',
+ },
},
exits: {
@@ -57,7 +60,14 @@ module.exports = {
throw Errors.USER_NOT_FOUND;
}
- const values = _.pick(inputs, ['isAdmin', 'name', 'avatar', 'phone', 'organization']);
+ const values = _.pick(inputs, [
+ 'isAdmin',
+ 'name',
+ 'avatar',
+ 'phone',
+ 'organization',
+ 'subscribeToOwnCards',
+ ]);
user = await sails.helpers.updateUser(user, values, this.req);
diff --git a/server/api/helpers/create-card.js b/server/api/helpers/create-card.js
index 435c81f1..800c8c40 100644
--- a/server/api/helpers/create-card.js
+++ b/server/api/helpers/create-card.js
@@ -49,6 +49,17 @@ module.exports = {
boardId: inputs.list.boardId,
}).fetch();
+ if (inputs.user.subscribeToOwnCards) {
+ await CardSubscription.create({
+ cardId: card.id,
+ userId: inputs.user.id,
+ }).tolerate('E_UNIQUE');
+
+ card.isSubscribed = true;
+ } else {
+ card.isSubscribed = false;
+ }
+
sails.sockets.broadcast(
`board:${card.boardId}`,
'cardCreate',
diff --git a/server/api/models/User.js b/server/api/models/User.js
index ae16ba29..d73dad16 100755
--- a/server/api/models/User.js
+++ b/server/api/models/User.js
@@ -52,6 +52,11 @@ module.exports = {
isNotEmptyString: true,
allowNull: true,
},
+ subscribeToOwnCards: {
+ type: 'boolean',
+ defaultsTo: false,
+ columnName: 'subscribe_to_own_cards',
+ },
deletedAt: {
type: 'ref',
columnName: 'deleted_at',
diff --git a/server/db/migrations/20180721220409_create_user_account_table.js b/server/db/migrations/20180721220409_create_user_account_table.js
index 57ee757e..edec086b 100755
--- a/server/db/migrations/20180721220409_create_user_account_table.js
+++ b/server/db/migrations/20180721220409_create_user_account_table.js
@@ -13,6 +13,7 @@ module.exports.up = (knex) =>
table.text('avatar');
table.text('phone');
table.text('organization');
+ table.boolean('subscribe_to_own_cards').notNullable();
table.timestamp('created_at', true);
table.timestamp('updated_at', true);
diff --git a/server/db/seeds/default.js b/server/db/seeds/default.js
index 14d89750..1e52fb23 100644
--- a/server/db/seeds/default.js
+++ b/server/db/seeds/default.js
@@ -9,6 +9,7 @@ exports.seed = (knex) => {
isAdmin: true,
name: 'Demo Demo',
username: 'demo',
+ subscribeToOwnCards: false,
createdAt: date,
updatedAt: date,
});