Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
513f9a8ee5 | ||
|
|
e051f624a8 | ||
|
|
172f4fcf34 | ||
|
|
9f16881965 | ||
|
|
4e876922f8 | ||
|
|
d82d928e29 | ||
|
|
94dc83706c | ||
|
|
b08e731419 | ||
|
|
1ce0fac281 | ||
|
|
e3d00c8791 | ||
|
|
e1a0b635ea |
+1
-1
@@ -26,7 +26,7 @@ COPY server .
|
||||
RUN cp .env.sample .env
|
||||
|
||||
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/project-background-images
|
||||
|
||||
@@ -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
+42
@@ -63,6 +63,7 @@
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"jest-enzyme": "^7.1.2",
|
||||
"prettier": "2.7.1",
|
||||
"react-app-rewired": "^2.2.1",
|
||||
"react-test-renderer": "^17.0.2"
|
||||
}
|
||||
},
|
||||
@@ -18665,6 +18666,30 @@
|
||||
"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": {
|
||||
"version": "13.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz",
|
||||
@@ -38717,6 +38742,23 @@
|
||||
"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": {
|
||||
"version": "13.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz",
|
||||
|
||||
+5
-4
@@ -2,11 +2,11 @@
|
||||
"name": "planka-client",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "react-scripts build",
|
||||
"build": "react-app-rewired build",
|
||||
"eject": "react-scripts eject",
|
||||
"lint": "eslint --ext js,jsx src",
|
||||
"start": "react-scripts start",
|
||||
"test": "react-scripts test"
|
||||
"lint": "eslint --ext js,jsx src config-overrides.js",
|
||||
"start": "react-app-rewired start",
|
||||
"test": "react-app-rewired test"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
@@ -120,6 +120,7 @@
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"jest-enzyme": "^7.1.2",
|
||||
"prettier": "2.7.1",
|
||||
"react-app-rewired": "^2.2.1",
|
||||
"react-test-renderer": "^17.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
-->
|
||||
<title>Planka</title>
|
||||
</head>
|
||||
<script>window.BASE_URL = "%PUBLIC_URL%";</script>
|
||||
<body id="app">
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -5,7 +5,7 @@ import Config from '../constants/Config';
|
||||
|
||||
const io = sailsIOClient(socketIOClient);
|
||||
|
||||
io.sails.url = Config.SERVER_BASE_URL;
|
||||
io.sails.url = Config.SERVER_HOST_NAME;
|
||||
io.sails.autoConnect = false;
|
||||
io.sails.reconnection = true;
|
||||
io.sails.useCORSRouteToGetCookie = false;
|
||||
@@ -13,6 +13,7 @@ io.sails.environment = process.env.NODE_ENV;
|
||||
|
||||
const { socket } = io;
|
||||
|
||||
socket.path = `${Config.BASE_PATH}/socket.io`;
|
||||
socket.connect = socket._connect; // eslint-disable-line no-underscore-dangle
|
||||
|
||||
['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].forEach((method) => {
|
||||
|
||||
+3
-3
@@ -19,7 +19,7 @@ const BoardMembershipPermissionsSelectStep = React.memo(
|
||||
...defaultData,
|
||||
}));
|
||||
|
||||
const handleRoleSelectClick = useCallback((role) => {
|
||||
const handleSelectRoleClick = useCallback((role) => {
|
||||
setData((prevData) => ({
|
||||
...prevData,
|
||||
role,
|
||||
@@ -50,7 +50,7 @@ const BoardMembershipPermissionsSelectStep = React.memo(
|
||||
<Menu secondary vertical className={styles.menu}>
|
||||
<Menu.Item
|
||||
active={data.role === BoardMembershipRoles.EDITOR}
|
||||
onClick={() => handleRoleSelectClick(BoardMembershipRoles.EDITOR)}
|
||||
onClick={() => handleSelectRoleClick(BoardMembershipRoles.EDITOR)}
|
||||
>
|
||||
<div className={styles.menuItemTitle}>{t('common.editor')}</div>
|
||||
<div className={styles.menuItemDescription}>
|
||||
@@ -59,7 +59,7 @@ const BoardMembershipPermissionsSelectStep = React.memo(
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
active={data.role === BoardMembershipRoles.VIEWER}
|
||||
onClick={() => handleRoleSelectClick(BoardMembershipRoles.VIEWER)}
|
||||
onClick={() => handleSelectRoleClick(BoardMembershipRoles.VIEWER)}
|
||||
>
|
||||
<div className={styles.menuItemTitle}>{t('common.viewer')}</div>
|
||||
<div className={styles.menuItemDescription}>{t('common.canOnlyViewBoard')}</div>
|
||||
|
||||
@@ -125,7 +125,7 @@ const Card = React.memo(
|
||||
startedAt={timer.startedAt}
|
||||
total={timer.total}
|
||||
size="tiny"
|
||||
onClick={handleToggleTimerClick}
|
||||
onClick={canEdit ? handleToggleTimerClick : undefined}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
@@ -166,14 +166,11 @@ const Card = React.memo(
|
||||
{canEdit && (
|
||||
<ActionsPopup
|
||||
card={{
|
||||
id,
|
||||
name,
|
||||
dueDate,
|
||||
timer,
|
||||
boardId,
|
||||
listId,
|
||||
projectId,
|
||||
isPersisted,
|
||||
}}
|
||||
projectsToLists={allProjectsToLists}
|
||||
boardMemberships={allBoardMemberships}
|
||||
|
||||
@@ -298,17 +298,19 @@ const CardModal = React.memo(
|
||||
<Timer startedAt={timer.startedAt} total={timer.total} />
|
||||
)}
|
||||
</span>
|
||||
<button
|
||||
onClick={handleToggleTimerClick}
|
||||
type="button"
|
||||
className={classNames(styles.attachment, styles.dueDate)}
|
||||
>
|
||||
<Icon
|
||||
name={timer.startedAt ? 'pause' : 'play'}
|
||||
size="small"
|
||||
className={styles.addAttachment}
|
||||
/>
|
||||
</button>
|
||||
{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>
|
||||
|
||||
@@ -10,12 +10,13 @@ import Editor from './Editor';
|
||||
|
||||
import styles from './AddStep.module.scss';
|
||||
|
||||
const AddStep = React.memo(({ onCreate, onBack }) => {
|
||||
const AddStep = React.memo(({ defaultData, onCreate, onBack }) => {
|
||||
const [t] = useTranslation();
|
||||
|
||||
const [data, handleFieldChange] = useForm(() => ({
|
||||
name: '',
|
||||
color: LabelColors[0],
|
||||
...defaultData,
|
||||
}));
|
||||
|
||||
const handleSubmit = useCallback(() => {
|
||||
@@ -46,6 +47,7 @@ const AddStep = React.memo(({ onCreate, onBack }) => {
|
||||
});
|
||||
|
||||
AddStep.propTypes = {
|
||||
defaultData: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||
onCreate: PropTypes.func.isRequired,
|
||||
onBack: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
@@ -84,7 +84,15 @@ const LabelsStep = React.memo(
|
||||
if (step) {
|
||||
switch (step.type) {
|
||||
case StepTypes.ADD:
|
||||
return <AddStep onCreate={onCreate} onBack={handleBack} />;
|
||||
return (
|
||||
<AddStep
|
||||
defaultData={{
|
||||
name: search,
|
||||
}}
|
||||
onCreate={onCreate}
|
||||
onBack={handleBack}
|
||||
/>
|
||||
);
|
||||
case StepTypes.EDIT: {
|
||||
const currentItem = items.find((item) => item.id === step.params.id);
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
const { BASE_URL } = window;
|
||||
const BASE_PATH = BASE_URL.replace(/^.*\/\/[^/]*(.*)[^?#]*.*$/, '$1');
|
||||
|
||||
const 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_VERSION_KEY = 'accessTokenVersion';
|
||||
@@ -10,7 +15,9 @@ const POSITION_GAP = 65535;
|
||||
const ACTIVITIES_LIMIT = 50;
|
||||
|
||||
export default {
|
||||
BASE_PATH,
|
||||
SERVER_BASE_URL,
|
||||
SERVER_HOST_NAME,
|
||||
ACCESS_TOKEN_KEY,
|
||||
ACCESS_TOKEN_VERSION_KEY,
|
||||
ACCESS_TOKEN_VERSION,
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
const ROOT = '/';
|
||||
const LOGIN = '/login';
|
||||
const PROJECTS = '/projects/:id';
|
||||
const BOARDS = '/boards/:id';
|
||||
const CARDS = '/cards/:id';
|
||||
import Config from './Config';
|
||||
|
||||
const ROOT = `${Config.BASE_PATH}/`;
|
||||
const LOGIN = `${Config.BASE_PATH}/login`;
|
||||
const PROJECTS = `${Config.BASE_PATH}/projects/:id`;
|
||||
const BOARDS = `${Config.BASE_PATH}/boards/:id`;
|
||||
const CARDS = `${Config.BASE_PATH}/cards/:id`;
|
||||
|
||||
export default {
|
||||
ROOT,
|
||||
|
||||
@@ -4,11 +4,11 @@ export default {
|
||||
dateFns,
|
||||
|
||||
format: {
|
||||
date: 'd/M/yyyy',
|
||||
date: 'd.MM.yyyy',
|
||||
time: 'p',
|
||||
dateTime: '$t(format:date) $t(format:time)',
|
||||
longDate: 'MMM d',
|
||||
longDateTime: "d MMMM 'at' p",
|
||||
longDate: 'd. MMM',
|
||||
longDateTime: "d. MMMM 'um' p",
|
||||
},
|
||||
|
||||
translation: {
|
||||
@@ -23,7 +23,7 @@ export default {
|
||||
administrator: 'Administrator',
|
||||
all: 'Alle',
|
||||
allChangesWillBeAutomaticallySavedAfterConnectionRestored:
|
||||
'Alle Änderungen werden automatisch gespeichert,<br />sobald die Verbindung wiederhergestellt wurde',
|
||||
'Alle Änderungen werden automatisch gespeichert, sobald die Verbindung wiederhergestellt wurde.',
|
||||
areYouSureYouWantToDeleteThisAttachment:
|
||||
'Sind Sie sicher, dass Sie diesen Anhang löschen möchten?',
|
||||
areYouSureYouWantToDeleteThisBoard: 'Sind Sie sicher, dass Sie dieses Board löschen möchten?',
|
||||
@@ -55,10 +55,11 @@ export default {
|
||||
color: 'Farbe',
|
||||
createBoard_title: 'Board 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',
|
||||
createTextFile_title: 'Textdatei erstellen',
|
||||
currentPassword: 'Derzeitiges Password',
|
||||
currentPassword: 'Derzeitiges Passwort',
|
||||
dangerZone_title: 'Gefährlicher Bereich',
|
||||
date: 'Datum',
|
||||
dueDate_title: 'Fälligkeitsdatum',
|
||||
@@ -73,18 +74,18 @@ export default {
|
||||
deleteUser_title: 'Benutzer löschen',
|
||||
description: 'Beschreibung',
|
||||
detectAutomatically: 'Automatische Erkennung',
|
||||
dropFileToUpload: 'Datei ablegen, um hochzuladen',
|
||||
dropFileToUpload: 'Datei ablegen, um sie hochzuladen',
|
||||
editAttachment_title: 'Anhang bearbieten',
|
||||
editAvatar_title: 'Avatar bearbeiten',
|
||||
editBoard_title: 'Board bearbeiten',
|
||||
editDueDate_title: 'Fälligkeitsdatum bearbeiten',
|
||||
editEmail_title: 'E-Mail bearbeiten',
|
||||
editEmail_title: 'E-Mail-Adresse bearbeiten',
|
||||
editLabel_title: 'Label bearbeiten',
|
||||
editPassword_title: 'Passwort ändern',
|
||||
editTimer_title: 'Timer bearbeiten',
|
||||
editUsername_title: 'Benutzername ändern',
|
||||
email: 'E-Mail',
|
||||
emailAlreadyInUse: 'E-Mail bereits in Verwendung',
|
||||
email: 'E-Mail-Adresse',
|
||||
emailAlreadyInUse: 'E-Mail-Adresse bereits in Verwendung',
|
||||
enterCardTitle: 'Kartentitel eingeben...',
|
||||
enterDescription: 'Beschreibung eingeben...',
|
||||
enterFilename: 'Dateiname eingeben',
|
||||
@@ -108,7 +109,7 @@ export default {
|
||||
minutes: 'Minuten',
|
||||
moveCard_title: 'Karte verschieben',
|
||||
name: 'Name',
|
||||
newEmail: 'Neue E-Mail',
|
||||
newEmail: 'Neue E-Mail-Adresse',
|
||||
newPassword: 'Neues Passwort',
|
||||
newUsername: 'Neuer Benutzername',
|
||||
noConnectionToServer: 'Keine Verbindung zum Server',
|
||||
@@ -140,10 +141,10 @@ export default {
|
||||
time: 'Zeit',
|
||||
timer: 'Timer',
|
||||
title: 'Titel',
|
||||
userActions_title: 'Benutzerraktionen',
|
||||
userActions_title: 'Benutzeraktionen',
|
||||
userAddedThisCardToList: '<0>{{user}}</0><1> hat diese Karte hinzugefügt zu {{list}}</1>',
|
||||
userLeftNewCommentToCard:
|
||||
'{{user}} hat einen neuen Kommentar verfasst «{{comment}}» to <2>{{card}}</2>',
|
||||
'{{user}} hat einen neuen Kommentar verfasst: «{{comment}}» in <2>{{card}}</2>',
|
||||
userMovedCardFromListToList:
|
||||
'{{user}} bewegte <2>{{card}}</2> von {{fromList}} nach {{toList}}',
|
||||
userMovedThisCardFromListToList:
|
||||
@@ -190,7 +191,7 @@ export default {
|
||||
edit: 'Bearbeiten',
|
||||
editDueDate_title: 'Fälligkeitsdatum bearbeiten',
|
||||
editDescription_title: 'Beschreibung ändern',
|
||||
editEmail_title: 'E-Mail bearbeiten',
|
||||
editEmail_title: 'E-Mail-Adresse bearbeiten',
|
||||
editPassword_title: 'Passwort ändern',
|
||||
editTimer_title: 'Timer bearbeiten',
|
||||
editTitle_title: 'Titel bearbeiten',
|
||||
@@ -199,7 +200,7 @@ export default {
|
||||
leaveBoard: 'Board verlassen',
|
||||
leaveProject: 'Projekt verlassen',
|
||||
logOut_title: 'Ausloggen',
|
||||
makeCover_title: 'als Vorschau festlegen',
|
||||
makeCover_title: 'Als Vorschau festlegen',
|
||||
move: 'Verschieben',
|
||||
moveCard_title: 'Karte bewegen',
|
||||
remove: 'Löschen',
|
||||
@@ -216,7 +217,7 @@ export default {
|
||||
start: 'Start',
|
||||
stop: 'Stopp',
|
||||
subscribe: 'Abonnieren',
|
||||
unsubscribe: 'Deabonnieren',
|
||||
unsubscribe: 'De-abonnieren',
|
||||
uploadNewAvatar: 'Neuen Avatar hochladen',
|
||||
uploadNewImage: 'Neues Bild hochladen',
|
||||
},
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
export default {
|
||||
translation: {
|
||||
common: {
|
||||
emailOrUsername: 'E-mail oder Benutzername',
|
||||
invalidEmailOrUsername: 'Ungültige E-mail oder Benutzername',
|
||||
emailOrUsername: 'E-Mail-Adresse oder Benutzername',
|
||||
invalidEmailOrUsername: 'Ungültige E-Mail-Adresse oder Benutzername',
|
||||
invalidPassword: 'Ungültiges Passwort',
|
||||
logInToPlanka: 'Einloggen',
|
||||
noInternetConnection: 'Keine Internetverbindung',
|
||||
pageNotFound_title: 'Seite nicht gefunden',
|
||||
password: 'Passwort',
|
||||
projectManagement: 'Projekt Management',
|
||||
projectManagement: 'Projekt-Management',
|
||||
serverConnectionFailed: 'Serververbindung fehlgeschlagen',
|
||||
unknownError: 'Unbekannter Fehler, bitte später erneut versuchen',
|
||||
},
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "planka",
|
||||
"version": "1.8.1",
|
||||
"version": "1.8.4",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "planka",
|
||||
"version": "1.8.1",
|
||||
"version": "1.8.4",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "planka",
|
||||
"version": "1.8.1",
|
||||
"version": "1.8.4",
|
||||
"private": true,
|
||||
"homepage": "https://plankanban.github.io/planka",
|
||||
"repository": {
|
||||
|
||||
@@ -7,7 +7,7 @@ module.exports = {
|
||||
|
||||
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({
|
||||
id: membershipBoardIds,
|
||||
@@ -21,16 +21,6 @@ module.exports = {
|
||||
|
||||
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 projects = [...managerProjects, ...membershipProjects];
|
||||
|
||||
@@ -40,7 +30,17 @@ module.exports = {
|
||||
const users = await sails.helpers.users.getMany(userIds);
|
||||
|
||||
const managerBoards = await sails.helpers.projects.getBoards(managerProjectIds);
|
||||
|
||||
membershipBoards = membershipBoards.filter((membershipBoard) =>
|
||||
membershipProjectIds.includes(membershipBoard.projectId),
|
||||
);
|
||||
|
||||
const boards = [...managerBoards, ...membershipBoards];
|
||||
const boardIds = sails.helpers.utils.mapRecords(boards);
|
||||
|
||||
boardMemberships = boardMemberships.filter((boardMembership) =>
|
||||
boardIds.includes(boardMembership.boardId),
|
||||
);
|
||||
|
||||
return {
|
||||
items: projects,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
const { v4: uuid } = require('uuid');
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
record: {
|
||||
@@ -29,18 +31,9 @@ module.exports = {
|
||||
const boardMembership = await BoardMembership.destroyOne(inputs.record.id);
|
||||
|
||||
if (boardMembership) {
|
||||
sails.sockets.broadcast(
|
||||
`user:${boardMembership.userId}`,
|
||||
'boardMembershipDelete',
|
||||
{
|
||||
item: boardMembership,
|
||||
},
|
||||
inputs.request,
|
||||
);
|
||||
|
||||
const notifyBoard = () => {
|
||||
const notify = (room) => {
|
||||
sails.sockets.broadcast(
|
||||
`board:${boardMembership.boardId}`,
|
||||
room,
|
||||
'boardMembershipDelete',
|
||||
{
|
||||
item: boardMembership,
|
||||
@@ -54,16 +47,32 @@ module.exports = {
|
||||
inputs.project.id,
|
||||
);
|
||||
|
||||
if (isProjectManager) {
|
||||
notifyBoard();
|
||||
} else {
|
||||
// TODO: also remove if unsubscribed to user
|
||||
if (!isProjectManager) {
|
||||
sails.sockets.removeRoomMembersFromRooms(
|
||||
`user:${boardMembership.userId}`,
|
||||
`@user:${boardMembership.userId}`,
|
||||
`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;
|
||||
|
||||
@@ -17,16 +17,23 @@ module.exports = {
|
||||
const board = await Board.archiveOne(inputs.record.id);
|
||||
|
||||
if (board) {
|
||||
sails.sockets.leaveAll(`board:${board.id}`);
|
||||
sails.sockets.removeRoomMembersFromRooms(`board:${board.id}`, `board:${board.id}`);
|
||||
|
||||
sails.sockets.broadcast(
|
||||
`project:${board.projectId}`,
|
||||
'boardDelete',
|
||||
{
|
||||
item: board,
|
||||
},
|
||||
inputs.request,
|
||||
);
|
||||
const managerUserIds = await sails.helpers.projects.getManagerUserIds(board.projectId);
|
||||
const memberUserIds = await sails.helpers.boards.getMemberUserIds(board.id);
|
||||
|
||||
const userIds = _.union(managerUserIds, memberUserIds);
|
||||
|
||||
userIds.forEach((userId) => {
|
||||
sails.sockets.broadcast(
|
||||
`user:${userId}`,
|
||||
'boardDelete',
|
||||
{
|
||||
item: board,
|
||||
},
|
||||
inputs.request,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return board;
|
||||
|
||||
@@ -25,9 +25,10 @@ module.exports = {
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const userIds = await sails.helpers.projects.getManagerAndBoardMemberUserIds(
|
||||
inputs.record.projectId,
|
||||
);
|
||||
const managerUserIds = await sails.helpers.projects.getManagerUserIds(inputs.record.projectId);
|
||||
const memberUserIds = await sails.helpers.boards.getMemberUserIds(inputs.record.id);
|
||||
|
||||
const userIds = _.union(managerUserIds, memberUserIds);
|
||||
|
||||
if (!_.isUndefined(inputs.values.position)) {
|
||||
const boards = await sails.helpers.projects.getBoards(
|
||||
|
||||
@@ -26,7 +26,7 @@ module.exports = {
|
||||
const userIds = _.union(managerUserIds, memberUserIds);
|
||||
|
||||
userIds.forEach((userId) => {
|
||||
sails.sockets.removeRoomMembersFromRooms(`user:${userId}`, boardRooms);
|
||||
sails.sockets.removeRoomMembersFromRooms(`@user:${userId}`, boardRooms);
|
||||
|
||||
sails.sockets.broadcast(
|
||||
`user:${userId}`,
|
||||
|
||||
@@ -123,13 +123,13 @@ module.exports = {
|
||||
if (user.id === inputs.user.id && inputs.request && inputs.request.isSocket) {
|
||||
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.leaveAll(tempRoom);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
sails.sockets.leaveAll(`user:${user.id}`);
|
||||
sails.sockets.leaveAll(`@user:${user.id}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,10 @@ module.exports = function defineCurrentUserHook(sails) {
|
||||
accessToken,
|
||||
currentUser,
|
||||
});
|
||||
|
||||
if (req.isSocket) {
|
||||
sails.sockets.join(req, `@user:${currentUser.id}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ module.exports.views = {
|
||||
*
|
||||
*/
|
||||
|
||||
extension: 'html',
|
||||
extension: 'ejs',
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -36,4 +36,5 @@ module.exports.views = {
|
||||
*/
|
||||
|
||||
layout: false,
|
||||
locals: { BASE_URL: process.env.BASE_URL },
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user