Compare commits

..
8 Commits
22 changed files with 223 additions and 80 deletions
+1 -1
View File
@@ -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
+56
View File
@@ -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;
};
+42
View File
@@ -63,6 +63,7 @@
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"jest-enzyme": "^7.1.2", "jest-enzyme": "^7.1.2",
"prettier": "2.7.1", "prettier": "2.7.1",
"react-app-rewired": "^2.2.1",
"react-test-renderer": "^17.0.2" "react-test-renderer": "^17.0.2"
} }
}, },
@@ -18665,6 +18666,30 @@
"node": ">=14" "node": ">=14"
} }
}, },
"node_modules/react-app-rewired": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.2.1.tgz",
"integrity": "sha512-uFQWTErXeLDrMzOJHKp0h8P1z0LV9HzPGsJ6adOtGlA/B9WfT6Shh4j2tLTTGlXOfiVx6w6iWpp7SOC5pvk+gA==",
"dev": true,
"dependencies": {
"semver": "^5.6.0"
},
"bin": {
"react-app-rewired": "bin/index.js"
},
"peerDependencies": {
"react-scripts": ">=2.1.3"
}
},
"node_modules/react-app-rewired/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true,
"bin": {
"semver": "bin/semver"
}
},
"node_modules/react-beautiful-dnd": { "node_modules/react-beautiful-dnd": {
"version": "13.1.0", "version": "13.1.0",
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz", "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz",
@@ -38717,6 +38742,23 @@
"whatwg-fetch": "^3.6.2" "whatwg-fetch": "^3.6.2"
} }
}, },
"react-app-rewired": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.2.1.tgz",
"integrity": "sha512-uFQWTErXeLDrMzOJHKp0h8P1z0LV9HzPGsJ6adOtGlA/B9WfT6Shh4j2tLTTGlXOfiVx6w6iWpp7SOC5pvk+gA==",
"dev": true,
"requires": {
"semver": "^5.6.0"
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
}
}
},
"react-beautiful-dnd": { "react-beautiful-dnd": {
"version": "13.1.0", "version": "13.1.0",
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz", "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz",
+5 -4
View File
@@ -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": [
@@ -120,6 +120,7 @@
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"jest-enzyme": "^7.1.2", "jest-enzyme": "^7.1.2",
"prettier": "2.7.1", "prettier": "2.7.1",
"react-app-rewired": "^2.2.1",
"react-test-renderer": "^17.0.2" "react-test-renderer": "^17.0.2"
} }
} }
+1
View File
@@ -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>
+2 -1
View File
@@ -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,6 +13,7 @@ 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) => {
+3 -1
View File
@@ -10,12 +10,13 @@ import Editor from './Editor';
import styles from './AddStep.module.scss'; import styles from './AddStep.module.scss';
const AddStep = React.memo(({ onCreate, onBack }) => { const AddStep = React.memo(({ defaultData, onCreate, onBack }) => {
const [t] = useTranslation(); const [t] = useTranslation();
const [data, handleFieldChange] = useForm(() => ({ const [data, handleFieldChange] = useForm(() => ({
name: '', name: '',
color: LabelColors[0], color: LabelColors[0],
...defaultData,
})); }));
const handleSubmit = useCallback(() => { const handleSubmit = useCallback(() => {
@@ -46,6 +47,7 @@ const AddStep = React.memo(({ onCreate, onBack }) => {
}); });
AddStep.propTypes = { AddStep.propTypes = {
defaultData: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
onCreate: PropTypes.func.isRequired, onCreate: PropTypes.func.isRequired,
onBack: PropTypes.func.isRequired, onBack: PropTypes.func.isRequired,
}; };
@@ -84,7 +84,15 @@ const LabelsStep = React.memo(
if (step) { if (step) {
switch (step.type) { switch (step.type) {
case StepTypes.ADD: case StepTypes.ADD:
return <AddStep onCreate={onCreate} onBack={handleBack} />; return (
<AddStep
defaultData={{
name: search,
}}
onCreate={onCreate}
onBack={handleBack}
/>
);
case StepTypes.EDIT: { case StepTypes.EDIT: {
const currentItem = items.find((item) => item.id === step.params.id); const currentItem = items.find((item) => item.id === step.params.id);
+8 -1
View File
@@ -1,6 +1,11 @@
const { BASE_URL } = window;
const BASE_PATH = BASE_URL.replace(/^.*\/\/[^/]*(.*)[^?#]*.*$/, '$1');
const SERVER_BASE_URL = const SERVER_BASE_URL =
process.env.REACT_APP_SERVER_BASE_URL || process.env.REACT_APP_SERVER_BASE_URL ||
(process.env.NODE_ENV === 'production' ? '' : 'http://localhost:1337'); (process.env.NODE_ENV === 'production' ? BASE_URL : 'http://localhost:1337');
const SERVER_HOST_NAME = SERVER_BASE_URL.replace(/^(.*\/\/[^/?#]*).*$/, '$1');
const ACCESS_TOKEN_KEY = 'accessToken'; const ACCESS_TOKEN_KEY = 'accessToken';
const ACCESS_TOKEN_VERSION_KEY = 'accessTokenVersion'; const ACCESS_TOKEN_VERSION_KEY = 'accessTokenVersion';
@@ -10,7 +15,9 @@ const POSITION_GAP = 65535;
const ACTIVITIES_LIMIT = 50; const ACTIVITIES_LIMIT = 50;
export default { export default {
BASE_PATH,
SERVER_BASE_URL, SERVER_BASE_URL,
SERVER_HOST_NAME,
ACCESS_TOKEN_KEY, ACCESS_TOKEN_KEY,
ACCESS_TOKEN_VERSION_KEY, ACCESS_TOKEN_VERSION_KEY,
ACCESS_TOKEN_VERSION, ACCESS_TOKEN_VERSION,
+7 -5
View File
@@ -1,8 +1,10 @@
const ROOT = '/'; import Config from './Config';
const LOGIN = '/login';
const PROJECTS = '/projects/:id'; const ROOT = `${Config.BASE_PATH}/`;
const BOARDS = '/boards/:id'; const LOGIN = `${Config.BASE_PATH}/login`;
const CARDS = '/cards/:id'; const PROJECTS = `${Config.BASE_PATH}/projects/:id`;
const BOARDS = `${Config.BASE_PATH}/boards/:id`;
const CARDS = `${Config.BASE_PATH}/cards/:id`;
export default { export default {
ROOT, ROOT,
+17 -16
View File
@@ -4,11 +4,11 @@ export default {
dateFns, dateFns,
format: { format: {
date: 'd/M/yyyy', date: 'd.MM.yyyy',
time: 'p', time: 'p',
dateTime: '$t(format:date) $t(format:time)', dateTime: '$t(format:date) $t(format:time)',
longDate: 'MMM d', longDate: 'd. MMM',
longDateTime: "d MMMM 'at' p", longDateTime: "d. MMMM 'um' p",
}, },
translation: { translation: {
@@ -23,7 +23,7 @@ export default {
administrator: 'Administrator', administrator: 'Administrator',
all: 'Alle', all: 'Alle',
allChangesWillBeAutomaticallySavedAfterConnectionRestored: allChangesWillBeAutomaticallySavedAfterConnectionRestored:
'Alle Änderungen werden automatisch gespeichert,<br />sobald die Verbindung wiederhergestellt wurde', 'Alle Änderungen werden automatisch gespeichert, sobald die Verbindung wiederhergestellt wurde.',
areYouSureYouWantToDeleteThisAttachment: areYouSureYouWantToDeleteThisAttachment:
'Sind Sie sicher, dass Sie diesen Anhang löschen möchten?', 'Sind Sie sicher, dass Sie diesen Anhang löschen möchten?',
areYouSureYouWantToDeleteThisBoard: 'Sind Sie sicher, dass Sie dieses Board löschen möchten?', areYouSureYouWantToDeleteThisBoard: 'Sind Sie sicher, dass Sie dieses Board löschen möchten?',
@@ -55,10 +55,11 @@ export default {
color: 'Farbe', color: 'Farbe',
createBoard_title: 'Board erstellen', createBoard_title: 'Board erstellen',
createLabel_title: 'Label erstellen', createLabel_title: 'Label erstellen',
createNewOneOrSelectExistingOne: 'Ein Neues erstellen, oder <br />ein Bestehendes auswählen', createNewOneOrSelectExistingOne:
'Erstellen Sie ein neues oder wählen Sie ein bestehendes aus.',
createProject_title: 'Projekt erstellen', createProject_title: 'Projekt erstellen',
createTextFile_title: 'Textdatei erstellen', createTextFile_title: 'Textdatei erstellen',
currentPassword: 'Derzeitiges Password', currentPassword: 'Derzeitiges Passwort',
dangerZone_title: 'Gefährlicher Bereich', dangerZone_title: 'Gefährlicher Bereich',
date: 'Datum', date: 'Datum',
dueDate_title: 'Fälligkeitsdatum', dueDate_title: 'Fälligkeitsdatum',
@@ -73,18 +74,18 @@ export default {
deleteUser_title: 'Benutzer löschen', deleteUser_title: 'Benutzer löschen',
description: 'Beschreibung', description: 'Beschreibung',
detectAutomatically: 'Automatische Erkennung', detectAutomatically: 'Automatische Erkennung',
dropFileToUpload: 'Datei ablegen, um hochzuladen', dropFileToUpload: 'Datei ablegen, um sie hochzuladen',
editAttachment_title: 'Anhang bearbieten', editAttachment_title: 'Anhang bearbieten',
editAvatar_title: 'Avatar bearbeiten', editAvatar_title: 'Avatar bearbeiten',
editBoard_title: 'Board bearbeiten', editBoard_title: 'Board bearbeiten',
editDueDate_title: 'Fälligkeitsdatum bearbeiten', editDueDate_title: 'Fälligkeitsdatum bearbeiten',
editEmail_title: 'E-Mail bearbeiten', editEmail_title: 'E-Mail-Adresse bearbeiten',
editLabel_title: 'Label bearbeiten', editLabel_title: 'Label bearbeiten',
editPassword_title: 'Passwort ändern', editPassword_title: 'Passwort ändern',
editTimer_title: 'Timer bearbeiten', editTimer_title: 'Timer bearbeiten',
editUsername_title: 'Benutzername ändern', editUsername_title: 'Benutzername ändern',
email: 'E-Mail', email: 'E-Mail-Adresse',
emailAlreadyInUse: 'E-Mail bereits in Verwendung', emailAlreadyInUse: 'E-Mail-Adresse bereits in Verwendung',
enterCardTitle: 'Kartentitel eingeben...', enterCardTitle: 'Kartentitel eingeben...',
enterDescription: 'Beschreibung eingeben...', enterDescription: 'Beschreibung eingeben...',
enterFilename: 'Dateiname eingeben', enterFilename: 'Dateiname eingeben',
@@ -108,7 +109,7 @@ export default {
minutes: 'Minuten', minutes: 'Minuten',
moveCard_title: 'Karte verschieben', moveCard_title: 'Karte verschieben',
name: 'Name', name: 'Name',
newEmail: 'Neue E-Mail', newEmail: 'Neue E-Mail-Adresse',
newPassword: 'Neues Passwort', newPassword: 'Neues Passwort',
newUsername: 'Neuer Benutzername', newUsername: 'Neuer Benutzername',
noConnectionToServer: 'Keine Verbindung zum Server', noConnectionToServer: 'Keine Verbindung zum Server',
@@ -140,10 +141,10 @@ export default {
time: 'Zeit', time: 'Zeit',
timer: 'Timer', timer: 'Timer',
title: 'Titel', title: 'Titel',
userActions_title: 'Benutzerraktionen', userActions_title: 'Benutzeraktionen',
userAddedThisCardToList: '<0>{{user}}</0><1> hat diese Karte hinzugefügt zu {{list}}</1>', userAddedThisCardToList: '<0>{{user}}</0><1> hat diese Karte hinzugefügt zu {{list}}</1>',
userLeftNewCommentToCard: userLeftNewCommentToCard:
'{{user}} hat einen neuen Kommentar verfasst «{{comment}}» to <2>{{card}}</2>', '{{user}} hat einen neuen Kommentar verfasst: «{{comment}}» in <2>{{card}}</2>',
userMovedCardFromListToList: userMovedCardFromListToList:
'{{user}} bewegte <2>{{card}}</2> von {{fromList}} nach {{toList}}', '{{user}} bewegte <2>{{card}}</2> von {{fromList}} nach {{toList}}',
userMovedThisCardFromListToList: userMovedThisCardFromListToList:
@@ -190,7 +191,7 @@ export default {
edit: 'Bearbeiten', edit: 'Bearbeiten',
editDueDate_title: 'Fälligkeitsdatum bearbeiten', editDueDate_title: 'Fälligkeitsdatum bearbeiten',
editDescription_title: 'Beschreibung ändern', editDescription_title: 'Beschreibung ändern',
editEmail_title: 'E-Mail bearbeiten', editEmail_title: 'E-Mail-Adresse bearbeiten',
editPassword_title: 'Passwort ändern', editPassword_title: 'Passwort ändern',
editTimer_title: 'Timer bearbeiten', editTimer_title: 'Timer bearbeiten',
editTitle_title: 'Titel bearbeiten', editTitle_title: 'Titel bearbeiten',
@@ -199,7 +200,7 @@ export default {
leaveBoard: 'Board verlassen', leaveBoard: 'Board verlassen',
leaveProject: 'Projekt verlassen', leaveProject: 'Projekt verlassen',
logOut_title: 'Ausloggen', logOut_title: 'Ausloggen',
makeCover_title: 'als Vorschau festlegen', makeCover_title: 'Als Vorschau festlegen',
move: 'Verschieben', move: 'Verschieben',
moveCard_title: 'Karte bewegen', moveCard_title: 'Karte bewegen',
remove: 'Löschen', remove: 'Löschen',
@@ -216,7 +217,7 @@ export default {
start: 'Start', start: 'Start',
stop: 'Stopp', stop: 'Stopp',
subscribe: 'Abonnieren', subscribe: 'Abonnieren',
unsubscribe: 'Deabonnieren', unsubscribe: 'De-abonnieren',
uploadNewAvatar: 'Neuen Avatar hochladen', uploadNewAvatar: 'Neuen Avatar hochladen',
uploadNewImage: 'Neues Bild hochladen', uploadNewImage: 'Neues Bild hochladen',
}, },
+3 -3
View File
@@ -1,14 +1,14 @@
export default { export default {
translation: { translation: {
common: { common: {
emailOrUsername: 'E-mail oder Benutzername', emailOrUsername: 'E-Mail-Adresse oder Benutzername',
invalidEmailOrUsername: 'Ungültige E-mail oder Benutzername', invalidEmailOrUsername: 'Ungültige E-Mail-Adresse oder Benutzername',
invalidPassword: 'Ungültiges Passwort', invalidPassword: 'Ungültiges Passwort',
logInToPlanka: 'Einloggen', logInToPlanka: 'Einloggen',
noInternetConnection: 'Keine Internetverbindung', noInternetConnection: 'Keine Internetverbindung',
pageNotFound_title: 'Seite nicht gefunden', pageNotFound_title: 'Seite nicht gefunden',
password: 'Passwort', password: 'Passwort',
projectManagement: 'Projekt Management', projectManagement: 'Projekt-Management',
serverConnectionFailed: 'Serververbindung fehlgeschlagen', serverConnectionFailed: 'Serververbindung fehlgeschlagen',
unknownError: 'Unbekannter Fehler, bitte später erneut versuchen', unknownError: 'Unbekannter Fehler, bitte später erneut versuchen',
}, },
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "planka", "name": "planka",
"version": "1.8.2", "version": "1.8.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "planka", "name": "planka",
"version": "1.8.2", "version": "1.8.4",
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "planka", "name": "planka",
"version": "1.8.2", "version": "1.8.4",
"private": true, "private": true,
"homepage": "https://plankanban.github.io/planka", "homepage": "https://plankanban.github.io/planka",
"repository": { "repository": {
+11 -11
View File
@@ -7,7 +7,7 @@ module.exports = {
let boardMemberships = await sails.helpers.users.getBoardMemberships(currentUser.id); let boardMemberships = await sails.helpers.users.getBoardMemberships(currentUser.id);
let membershipBoardIds = sails.helpers.utils.mapRecords(boardMemberships, 'boardId'); const membershipBoardIds = sails.helpers.utils.mapRecords(boardMemberships, 'boardId');
let membershipBoards = await sails.helpers.boards.getMany({ let membershipBoards = await sails.helpers.boards.getMany({
id: membershipBoardIds, id: membershipBoardIds,
@@ -21,16 +21,6 @@ module.exports = {
membershipProjectIds = sails.helpers.utils.mapRecords(membershipProjects); membershipProjectIds = sails.helpers.utils.mapRecords(membershipProjects);
membershipBoards = membershipBoards.filter((membershipBoard) =>
membershipProjectIds.includes(membershipBoard.projectId),
);
membershipBoardIds = sails.helpers.utils.mapRecords(membershipBoards);
boardMemberships = boardMemberships.filter((boardMembership) =>
membershipBoardIds.includes(boardMembership.boardId),
);
const projectIds = [...managerProjectIds, ...membershipProjectIds]; const projectIds = [...managerProjectIds, ...membershipProjectIds];
const projects = [...managerProjects, ...membershipProjects]; const projects = [...managerProjects, ...membershipProjects];
@@ -40,7 +30,17 @@ module.exports = {
const users = await sails.helpers.users.getMany(userIds); const users = await sails.helpers.users.getMany(userIds);
const managerBoards = await sails.helpers.projects.getBoards(managerProjectIds); const managerBoards = await sails.helpers.projects.getBoards(managerProjectIds);
membershipBoards = membershipBoards.filter((membershipBoard) =>
membershipProjectIds.includes(membershipBoard.projectId),
);
const boards = [...managerBoards, ...membershipBoards]; const boards = [...managerBoards, ...membershipBoards];
const boardIds = sails.helpers.utils.mapRecords(boards);
boardMemberships = boardMemberships.filter((boardMembership) =>
boardIds.includes(boardMembership.boardId),
);
return { return {
items: projects, items: projects,
@@ -1,3 +1,5 @@
const { v4: uuid } = require('uuid');
module.exports = { module.exports = {
inputs: { inputs: {
record: { record: {
@@ -29,18 +31,9 @@ module.exports = {
const boardMembership = await BoardMembership.destroyOne(inputs.record.id); const boardMembership = await BoardMembership.destroyOne(inputs.record.id);
if (boardMembership) { if (boardMembership) {
sails.sockets.broadcast( const notify = (room) => {
`user:${boardMembership.userId}`,
'boardMembershipDelete',
{
item: boardMembership,
},
inputs.request,
);
const notifyBoard = () => {
sails.sockets.broadcast( sails.sockets.broadcast(
`board:${boardMembership.boardId}`, room,
'boardMembershipDelete', 'boardMembershipDelete',
{ {
item: boardMembership, item: boardMembership,
@@ -54,16 +47,32 @@ module.exports = {
inputs.project.id, inputs.project.id,
); );
if (isProjectManager) { if (!isProjectManager) {
notifyBoard();
} else {
// TODO: also remove if unsubscribed to user
sails.sockets.removeRoomMembersFromRooms( sails.sockets.removeRoomMembersFromRooms(
`user:${boardMembership.userId}`, `@user:${boardMembership.userId}`,
`board:${boardMembership.boardId}`, `board:${boardMembership.boardId}`,
notifyBoard, () => {
notify(`board:${boardMembership.boardId}`);
},
); );
} }
notify(`user:${boardMembership.userId}`);
if (isProjectManager) {
const tempRoom = uuid();
sails.sockets.addRoomMembersToRooms(`board:${boardMembership.boardId}`, tempRoom, () => {
sails.sockets.removeRoomMembersFromRooms(
`user:${boardMembership.userId}`,
tempRoom,
() => {
notify(tempRoom);
sails.sockets.removeRoomMembersFromRooms(tempRoom, tempRoom);
},
);
});
}
} }
return boardMembership; return boardMembership;
+16 -9
View File
@@ -17,16 +17,23 @@ module.exports = {
const board = await Board.archiveOne(inputs.record.id); const board = await Board.archiveOne(inputs.record.id);
if (board) { if (board) {
sails.sockets.leaveAll(`board:${board.id}`); sails.sockets.removeRoomMembersFromRooms(`board:${board.id}`, `board:${board.id}`);
sails.sockets.broadcast( const managerUserIds = await sails.helpers.projects.getManagerUserIds(board.projectId);
`project:${board.projectId}`, const memberUserIds = await sails.helpers.boards.getMemberUserIds(board.id);
'boardDelete',
{ const userIds = _.union(managerUserIds, memberUserIds);
item: board,
}, userIds.forEach((userId) => {
inputs.request, sails.sockets.broadcast(
); `user:${userId}`,
'boardDelete',
{
item: board,
},
inputs.request,
);
});
} }
return board; return board;
+4 -3
View File
@@ -25,9 +25,10 @@ module.exports = {
}, },
async fn(inputs) { async fn(inputs) {
const userIds = await sails.helpers.projects.getManagerAndBoardMemberUserIds( const managerUserIds = await sails.helpers.projects.getManagerUserIds(inputs.record.projectId);
inputs.record.projectId, const memberUserIds = await sails.helpers.boards.getMemberUserIds(inputs.record.id);
);
const userIds = _.union(managerUserIds, memberUserIds);
if (!_.isUndefined(inputs.values.position)) { if (!_.isUndefined(inputs.values.position)) {
const boards = await sails.helpers.projects.getBoards( const boards = await sails.helpers.projects.getBoards(
+1 -1
View File
@@ -26,7 +26,7 @@ module.exports = {
const userIds = _.union(managerUserIds, memberUserIds); const userIds = _.union(managerUserIds, memberUserIds);
userIds.forEach((userId) => { userIds.forEach((userId) => {
sails.sockets.removeRoomMembersFromRooms(`user:${userId}`, boardRooms); sails.sockets.removeRoomMembersFromRooms(`@user:${userId}`, boardRooms);
sails.sockets.broadcast( sails.sockets.broadcast(
`user:${userId}`, `user:${userId}`,
+2 -2
View File
@@ -123,13 +123,13 @@ module.exports = {
if (user.id === inputs.user.id && inputs.request && inputs.request.isSocket) { if (user.id === inputs.user.id && inputs.request && inputs.request.isSocket) {
const tempRoom = uuid(); const tempRoom = uuid();
sails.sockets.addRoomMembersToRooms(`user:${user.id}`, tempRoom, () => { sails.sockets.addRoomMembersToRooms(`@user:${user.id}`, tempRoom, () => {
sails.sockets.leave(inputs.request, tempRoom, () => { sails.sockets.leave(inputs.request, tempRoom, () => {
sails.sockets.leaveAll(tempRoom); sails.sockets.leaveAll(tempRoom);
}); });
}); });
} else { } else {
sails.sockets.leaveAll(`user:${user.id}`); sails.sockets.leaveAll(`@user:${user.id}`);
} }
} }
+4
View File
@@ -59,6 +59,10 @@ module.exports = function defineCurrentUserHook(sails) {
accessToken, accessToken,
currentUser, currentUser,
}); });
if (req.isSocket) {
sails.sockets.join(req, `@user:${currentUser.id}`);
}
} }
} }
+2 -1
View File
@@ -24,7 +24,7 @@ module.exports.views = {
* *
*/ */
extension: 'html', extension: 'ejs',
/** /**
* *
@@ -36,4 +36,5 @@ module.exports.views = {
*/ */
layout: false, layout: false,
locals: { BASE_URL: process.env.BASE_URL },
}; };