Compare commits
21
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0f584e814 | ||
|
|
135f5eccb5 | ||
|
|
10001db8cf | ||
|
|
7ee351fe30 | ||
|
|
73746b83d1 | ||
|
|
f9a7b38ce9 | ||
|
|
1f261fe7b6 | ||
|
|
80bee30463 | ||
|
|
a9957481b6 | ||
|
|
36b05a5478 | ||
|
|
af91512abf | ||
|
|
8fd0f682d9 | ||
|
|
9699fbe76a | ||
|
|
4176a62f1a | ||
|
|
c12f0844d7 | ||
|
|
e6644eb745 | ||
|
|
b2e1fba9a0 | ||
|
|
818ae4a6df | ||
|
|
0de0e809ac | ||
|
|
da727c0a0b | ||
|
|
4841a65c77 |
@@ -15,13 +15,13 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.2.6
|
||||
version: 0.2.8
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "1.21.0"
|
||||
appVersion: "1.22.0"
|
||||
|
||||
dependencies:
|
||||
- alias: postgresql
|
||||
|
||||
@@ -11,6 +11,10 @@ spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "planka.selectorLabels" . | nindent 6 }}
|
||||
{{- if .Values.persistence.enabled }}
|
||||
strategy:
|
||||
type: Recreate
|
||||
{{- end }}
|
||||
template:
|
||||
metadata:
|
||||
{{- with .Values.podAnnotations }}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
REACT_APP_VERSION=1.21.0
|
||||
Generated
+2052
-7107
File diff suppressed because it is too large
Load Diff
+12
-11
@@ -65,7 +65,7 @@
|
||||
"dequal": "^2.0.3",
|
||||
"easymde": "^2.18.0",
|
||||
"history": "^5.3.0",
|
||||
"i18next": "^23.12.2",
|
||||
"i18next": "^23.15.1",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"initials": "^3.1.2",
|
||||
"js-cookie": "^3.0.5",
|
||||
@@ -77,18 +77,18 @@
|
||||
"node-sass": "^9.0.0",
|
||||
"photoswipe": "^5.4.4",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.2.0",
|
||||
"react": "18.2.0",
|
||||
"react-app-rewired": "^2.2.1",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-datepicker": "^4.25.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-dropzone": "^14.2.3",
|
||||
"react-i18next": "^15.0.0",
|
||||
"react-i18next": "^15.0.2",
|
||||
"react-input-mask": "^2.0.4",
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-photoswipe-gallery": "^2.2.7",
|
||||
"react-redux": "^8.1.3",
|
||||
"react-router-dom": "^6.23.1",
|
||||
"react-router-dom": "^6.26.2",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-simplemde-editor": "^5.2.0",
|
||||
"react-textarea-autosize": "^8.5.3",
|
||||
@@ -107,17 +107,18 @@
|
||||
"zxcvbn": "^4.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/jest-dom": "^6.4.5",
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"@testing-library/jest-dom": "^6.5.0",
|
||||
"@testing-library/react": "^15.0.7",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
"babel-preset-airbnb": "^5.0.0",
|
||||
"chai": "^4.4.1",
|
||||
"chai": "^4.5.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||
"eslint-plugin-react": "^7.34.2",
|
||||
"eslint-plugin-import": "^2.30.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.0",
|
||||
"eslint-plugin-react": "^7.36.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"react-test-renderer": "^18.2.0"
|
||||
"react-test-renderer": "18.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import http from './http';
|
||||
import socket from './socket';
|
||||
|
||||
/* Actions */
|
||||
|
||||
const createAccessToken = (data, headers) => http.post('/access-tokens', data, headers);
|
||||
const createAccessToken = (data, headers) =>
|
||||
http.post('/access-tokens?withHttpOnlyToken=true', data, headers);
|
||||
|
||||
const exchangeForAccessTokenUsingOidc = (data, headers) =>
|
||||
http.post('/access-tokens/exchange-using-oidc', data, headers);
|
||||
http.post('/access-tokens/exchange-using-oidc?withHttpOnlyToken=true', data, headers);
|
||||
|
||||
const deleteCurrentAccessToken = (headers) =>
|
||||
socket.delete('/access-tokens/me', undefined, headers);
|
||||
const deleteCurrentAccessToken = (headers) => http.delete('/access-tokens/me', undefined, headers);
|
||||
|
||||
export default {
|
||||
createAccessToken,
|
||||
|
||||
@@ -5,7 +5,7 @@ import Config from '../constants/Config';
|
||||
const http = {};
|
||||
|
||||
// TODO: add all methods
|
||||
['GET', 'POST'].forEach((method) => {
|
||||
['GET', 'POST', 'DELETE'].forEach((method) => {
|
||||
http[method.toLowerCase()] = (url, data, headers) => {
|
||||
const formData =
|
||||
data &&
|
||||
@@ -19,6 +19,7 @@ const http = {};
|
||||
method,
|
||||
headers,
|
||||
body: formData,
|
||||
credentials: 'include',
|
||||
})
|
||||
.then((response) =>
|
||||
response.json().then((body) => ({
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.dropzone {
|
||||
background: white;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
font-weight: bold;
|
||||
height: 100%;
|
||||
line-height: 30px;
|
||||
opacity: 0.7;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
.contentError {
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
font-weight: bold;
|
||||
height: 20px;
|
||||
width: 470px;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
color: #5e6c84;
|
||||
display: block;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
font-weight: bold;
|
||||
height: 100%;
|
||||
line-height: 80px;
|
||||
overflow: hidden;
|
||||
@@ -50,7 +50,7 @@
|
||||
.name {
|
||||
color: #17394d;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
.actionsTitle {
|
||||
color: #8c8c8c;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
font-weight: normal;
|
||||
letter-spacing: 0.04em;
|
||||
margin-top: 16px;
|
||||
text-transform: uppercase;
|
||||
@@ -158,7 +158,7 @@
|
||||
.headerTitle {
|
||||
color: #17394d;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
font-weight: bold;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
box-shadow: none;
|
||||
color: #17394d;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
font-weight: bold;
|
||||
line-height: 24px;
|
||||
margin: -5px;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
border-radius: 3px;
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
font-weight: 400;
|
||||
font-weight: normal;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
|
||||
|
||||
@@ -111,6 +111,7 @@
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 797px) {
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
background: rgba(9, 30, 66, 0.13);
|
||||
|
||||
@@ -18,6 +18,11 @@ const createMessage = (error) => {
|
||||
}
|
||||
|
||||
switch (error.message) {
|
||||
case 'Invalid credentials':
|
||||
return {
|
||||
type: 'error',
|
||||
content: 'common.invalidCredentials',
|
||||
};
|
||||
case 'Invalid email or username':
|
||||
return {
|
||||
type: 'error',
|
||||
@@ -116,6 +121,7 @@ const Login = React.memo(
|
||||
useEffect(() => {
|
||||
if (wasSubmitting && !isSubmitting && error) {
|
||||
switch (error.message) {
|
||||
case 'Invalid credentials':
|
||||
case 'Invalid email or username':
|
||||
emailOrUsernameField.current.select();
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
.wrapperTiny {
|
||||
font-size: 10px;
|
||||
font-weight: 400;
|
||||
height: 24px;
|
||||
line-height: 20px;
|
||||
padding: 2px 0;
|
||||
@@ -39,7 +38,6 @@
|
||||
|
||||
.wrapperSmall {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
height: 28px;
|
||||
padding: 8px 0;
|
||||
width: 28px;
|
||||
@@ -47,7 +45,6 @@
|
||||
|
||||
.wrapperMedium {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
height: 32px;
|
||||
padding: 10px 0;
|
||||
width: 32px;
|
||||
@@ -55,7 +52,6 @@
|
||||
|
||||
.wrapperLarge {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
height: 36px;
|
||||
padding: 12px 0 10px;
|
||||
width: 36px;
|
||||
@@ -63,7 +59,6 @@
|
||||
|
||||
.wrapperMassive {
|
||||
font-size: 36px;
|
||||
font-weight: 500;
|
||||
height: 100px;
|
||||
padding: 32px 0 10px;
|
||||
width: 100px;
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Image, Tab } from 'semantic-ui-react';
|
||||
|
||||
import Config from '../../constants/Config';
|
||||
import version from '../../version';
|
||||
|
||||
import logo from '../../assets/images/logo.png';
|
||||
|
||||
@@ -15,7 +15,7 @@ const AboutPane = React.memo(() => {
|
||||
<Tab.Pane attached={false} className={styles.wrapper}>
|
||||
<Image centered src={logo} size="large" />
|
||||
<div className={styles.version}>
|
||||
{t('common.version')} {Config.VERSION}
|
||||
{t('common.version')} {version}
|
||||
</div>
|
||||
</Tab.Pane>
|
||||
);
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
const VERSION = process.env.REACT_APP_VERSION;
|
||||
|
||||
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' ? BASE_URL : 'http://localhost:1337');
|
||||
const SERVER_BASE_PATH = SERVER_BASE_URL.replace(/^.*\/\/[^/]*(.*)[^?#]*.*$/, '$1');
|
||||
|
||||
const SERVER_BASE_PATH = SERVER_BASE_URL.replace(/^.*\/\/[^/]*(.*)[^?#]*.*$/, '$1');
|
||||
const SERVER_HOST_NAME = SERVER_BASE_URL.replace(/^(.*\/\/[^/?#]*).*$/, '$1');
|
||||
|
||||
const ACCESS_TOKEN_KEY = 'accessToken';
|
||||
@@ -18,7 +17,6 @@ const POSITION_GAP = 65535;
|
||||
const ACTIVITIES_LIMIT = 50;
|
||||
|
||||
export default {
|
||||
VERSION,
|
||||
BASE_PATH,
|
||||
SERVER_BASE_URL,
|
||||
SERVER_BASE_PATH,
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -64,7 +64,7 @@
|
||||
|
||||
.markdown-body b,
|
||||
.markdown-body strong {
|
||||
font-weight: 600;
|
||||
font-weight: bold; // 600
|
||||
}
|
||||
|
||||
.markdown-body dfn {
|
||||
@@ -73,7 +73,7 @@
|
||||
|
||||
.markdown-body h1 {
|
||||
margin: .67em 0;
|
||||
font-weight: 600;
|
||||
font-weight: bold; // 600
|
||||
padding-bottom: .3em;
|
||||
font-size: 2em;
|
||||
border-bottom: 1px solid hsla(210, 18%, 87%, 1);
|
||||
@@ -253,34 +253,34 @@
|
||||
.markdown-body h6 {
|
||||
margin-top: 24px;
|
||||
margin-bottom: 16px;
|
||||
font-weight: 600;
|
||||
font-weight: bold; // 600
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.markdown-body h2 {
|
||||
font-weight: 600;
|
||||
font-weight: bold; // 600
|
||||
padding-bottom: .3em;
|
||||
font-size: 1.5em;
|
||||
border-bottom: 1px solid hsla(210, 18%, 87%, 1);
|
||||
}
|
||||
|
||||
.markdown-body h3 {
|
||||
font-weight: 600;
|
||||
font-weight: bold; // 600
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
.markdown-body h4 {
|
||||
font-weight: 600;
|
||||
font-weight: bold; // 600
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.markdown-body h5 {
|
||||
font-weight: 600;
|
||||
font-weight: bold; // 600
|
||||
font-size: .875em;
|
||||
}
|
||||
|
||||
.markdown-body h6 {
|
||||
font-weight: 600;
|
||||
font-weight: bold; // 600
|
||||
font-size: .85em;
|
||||
color: #57606a;
|
||||
}
|
||||
@@ -481,7 +481,7 @@
|
||||
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
font-size: 1em;
|
||||
font-style: normal !important;
|
||||
font-weight: 400;
|
||||
font-weight: normal; // 400
|
||||
line-height: 1;
|
||||
vertical-align: -0.075em;
|
||||
}
|
||||
@@ -650,7 +650,7 @@
|
||||
margin-top: 16px;
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-weight: bold; // 600
|
||||
}
|
||||
|
||||
.markdown-body dl dd {
|
||||
@@ -659,7 +659,7 @@
|
||||
}
|
||||
|
||||
.markdown-body table th {
|
||||
font-weight: 600;
|
||||
font-weight: bold; // 600
|
||||
}
|
||||
|
||||
.markdown-body table th,
|
||||
@@ -868,7 +868,7 @@
|
||||
}
|
||||
|
||||
.markdown-body .csv-data th {
|
||||
font-weight: 600;
|
||||
font-weight: bold; // 600
|
||||
background: #f6f8fa;
|
||||
border-top: 0;
|
||||
}
|
||||
@@ -912,7 +912,7 @@
|
||||
}
|
||||
|
||||
.markdown-body .task-list-item label {
|
||||
font-weight: 400;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.markdown-body .task-list-item.enabled label {
|
||||
|
||||
Vendored
+2535
-2696
File diff suppressed because one or more lines are too long
@@ -3,6 +3,7 @@ export default {
|
||||
common: {
|
||||
emailOrUsername: 'E-mail or username',
|
||||
invalidEmailOrUsername: 'Invalid e-mail or username',
|
||||
invalidCredentials: 'Invalid credentials',
|
||||
invalidPassword: 'Invalid password',
|
||||
logInToPlanka: 'Log in to Planka',
|
||||
noInternetConnection: 'No internet connection',
|
||||
|
||||
@@ -43,7 +43,7 @@ export default {
|
||||
boardNotFound_title: 'Tablero no encontrado',
|
||||
cardActions_title: 'Acciones de las tarjetas',
|
||||
cardNotFound_title: 'tarjeta no encontrada',
|
||||
cardOrActionAreDeleted: 'La tarjeta o la acción está eliminada.',
|
||||
cardOrActionAreDeleted: 'La tarjeta o la acción está borrada.',
|
||||
color: 'Color',
|
||||
createBoard_title: 'Crear Tablero',
|
||||
createLabel_title: 'Crear Etiqueta',
|
||||
@@ -53,7 +53,7 @@ export default {
|
||||
currentPassword: 'Contraseña Actual',
|
||||
date: 'Fecha',
|
||||
dueDate_title: 'Fecha de Vencimiento',
|
||||
deleteAttachment_title: 'Eliminar Adjunto',
|
||||
deleteAttachment_title: 'Borrar Adjunto',
|
||||
deleteBoard_title: 'Borrar Tablero',
|
||||
deleteCard_title: 'Borrar tarjeta',
|
||||
deleteComment_title: 'Borrar Comentario',
|
||||
@@ -72,7 +72,7 @@ export default {
|
||||
editLabel_title: 'Editar Etiqueta',
|
||||
editPassword_title: 'Editar Contraseña',
|
||||
editStopwatch_title: 'Editar Temporizador',
|
||||
editUsername_title: 'Edit nombre de usuario',
|
||||
editUsername_title: 'Editar nombre de usuario',
|
||||
email: 'Correo',
|
||||
emailAlreadyInUse: 'El correo ya está en uso',
|
||||
enterCardTitle: 'Escribe el título de la tarjeta...',
|
||||
@@ -85,8 +85,8 @@ export default {
|
||||
filterByMembers_title: 'Filtrar por Miembros',
|
||||
fromComputer_title: 'Desde Computador',
|
||||
hours: 'Horas',
|
||||
invalidCurrentPassword: 'Contraseña actual invalida',
|
||||
labels: 'Etíquetas',
|
||||
invalidCurrentPassword: 'Contraseña actual inválida',
|
||||
labels: 'Etiquetas',
|
||||
list: 'Lista',
|
||||
listActions_title: 'Acciónes de Lista',
|
||||
members: 'Miembros',
|
||||
@@ -168,14 +168,14 @@ export default {
|
||||
deleteProject_title: 'Borrar Proyecto',
|
||||
deleteTask: 'Borrar tarea',
|
||||
deleteTask_title: 'Borrar Tarea',
|
||||
deleteUser: 'Delete usuario',
|
||||
deleteUser: 'Borrar usuario',
|
||||
edit: 'Editar',
|
||||
editDueDate_title: 'Editar Fecha de Vencimiento',
|
||||
editDescription_title: 'Editar Descripción',
|
||||
editEmail_title: 'Editar Correo',
|
||||
editPassword_title: 'Editar Contraseña',
|
||||
editStopwatch_title: 'Edit Temporizador',
|
||||
editTitle_title: 'Edit Título',
|
||||
editStopwatch_title: 'Editar Temporizador',
|
||||
editTitle_title: 'Editar Título',
|
||||
editUsername_title: 'Editar Nombre de Usuario',
|
||||
logOut_title: 'Cerrar Sesión',
|
||||
makeCover_title: 'Hacer Cubierta',
|
||||
|
||||
@@ -15,10 +15,12 @@ export default {
|
||||
|
||||
translation: {
|
||||
common: {
|
||||
aboutPlanka: 'À propos de Planka',
|
||||
account: 'Compte',
|
||||
actions: 'Actions',
|
||||
addAttachment_title: 'Ajouter une pièce jointe',
|
||||
addComment: 'Ajouter un commentaire',
|
||||
addManager_title: 'Ajouter un manager',
|
||||
addMember_title: 'Ajouter un membre',
|
||||
addUser_title: 'Ajouter un utilisateur',
|
||||
administrator: 'Administrateur',
|
||||
@@ -26,32 +28,43 @@ export default {
|
||||
allChangesWillBeAutomaticallySavedAfterConnectionRestored:
|
||||
'Toutes les modifications seront automatiquement enregistrées<br />une fois la connexion rétablie.',
|
||||
areYouSureYouWantToDeleteThisAttachment: 'Voulez-vous vraiment supprimer cette pièce jointe?',
|
||||
areYouSureYouWantToDeleteThisBoard: 'Êtes-vous sûr de vouloir supprimer ce forum?',
|
||||
areYouSureYouWantToDeleteThisBoard: 'Êtes-vous sûr de vouloir supprimer ce tableau?',
|
||||
areYouSureYouWantToDeleteThisCard: 'Voulez-vous vraiment supprimer cette carte?',
|
||||
areYouSureYouWantToDeleteThisComment: 'Êtes-vous sûr de vouloir supprimer ce commentaire?',
|
||||
areYouSureYouWantToDeleteThisLabel: 'Voulez-vous vraiment supprimer ce libellé?',
|
||||
areYouSureYouWantToDeleteThisLabel: 'Voulez-vous vraiment supprimer cette étiquette?',
|
||||
areYouSureYouWantToDeleteThisList: 'Êtes-vous sûr de vouloir supprimer cette liste?',
|
||||
areYouSureYouWantToDeleteThisProject: 'Êtes-vous sûr de vouloir supprimer ce projet?',
|
||||
areYouSureYouWantToDeleteThisTask: 'Êtes-vous sûr de vouloir supprimer cette tâche?',
|
||||
areYouSureYouWantToDeleteThisUser: 'Êtes-vous sûr de vouloir supprimer cet utilisateur?',
|
||||
areYouSureYouWantToLeaveBoard: 'Êtes-vous sûr de vouloir quitter ce tableau ?',
|
||||
areYouSureYouWantToLeaveProject: 'Êtes-vous sûr de vouloir quitter ce projet ?',
|
||||
areYouSureYouWantToRemoveThisManagerFromProject:
|
||||
'Êtes-vous sûr de vouloir supprimer ce manager du projet ?',
|
||||
areYouSureYouWantToRemoveThisMemberFromProject:
|
||||
'Êtes-vous sûr de vouloir supprimer ce membre du projet?',
|
||||
attachment: 'Attachement',
|
||||
attachment: 'Pièce jointe',
|
||||
attachments: 'Pièces jointes',
|
||||
authentication: 'Authentification',
|
||||
background: 'Arrière-plan',
|
||||
board: 'Tableau',
|
||||
boardNotFound_title: 'Carte non trouvée',
|
||||
canComment: 'Peut commenter',
|
||||
canEditContentOfBoard: 'Peut éditer le contenu du tableau.',
|
||||
canOnlyViewBoard: 'Peut uniquement voir le tableau.',
|
||||
cardActions_title: 'Actions sur la carte',
|
||||
cardNotFound_title: 'Carte non trouvée',
|
||||
cardOrActionAreDeleted: "La carte ou l'action sont supprimées.",
|
||||
color: 'Couleur',
|
||||
copy_inline: 'copie',
|
||||
createBoard_title: 'Créer un tableau',
|
||||
createLabel_title: 'Créer une étiquette',
|
||||
createNewOneOrSelectExistingOne: 'Créez-en un nouveau ou sélectionnez<br />un existant.',
|
||||
createProject_title: 'Créer un projet',
|
||||
createTextFile_title: 'Créer un fichier texte',
|
||||
currentPassword: 'Mot de passe actuel',
|
||||
dangerZone_title: 'Zone dangereuse',
|
||||
date: 'Date',
|
||||
dueDate: "Date d'échéance",
|
||||
dueDate_title: "Date d'échéance",
|
||||
deleteAttachment_title: 'Supprimer la pièce jointe',
|
||||
deleteBoard_title: 'Supprimer le tableau',
|
||||
@@ -63,67 +76,89 @@ export default {
|
||||
deleteTask_title: 'Supprimer la tâche',
|
||||
deleteUser_title: "Supprimer l'utilisateur",
|
||||
description: 'Description',
|
||||
detectAutomatically: 'Détecter automatiquement',
|
||||
dropFileToUpload: 'Déposer le fichier à télécharger',
|
||||
editor: 'Éditeur',
|
||||
editAttachment_title: 'Modifier la pièce jointe',
|
||||
editAvatar_title: 'Modifier Avatar',
|
||||
editBoard_title: 'Modifier le tableau',
|
||||
editDueDate_title: "Modifier la date d'échéance",
|
||||
editEmail_title: "Modifier l'e-mail",
|
||||
editEmail_title: "Modifier l'email",
|
||||
editInformation_title: 'Modifier les informations',
|
||||
editLabel_title: "Modifier l'étiquette",
|
||||
editPassword_title: 'Modifier le mot de passe',
|
||||
editPermissions_title: 'Modifier les permissions',
|
||||
editStopwatch_title: 'Modifier la minuterie',
|
||||
editUsername_title: "Modifier le nom d'utilisateur",
|
||||
email: 'E-mail',
|
||||
emailAlreadyInUse: 'Email déjà utilisé',
|
||||
enterCardTitle: 'Entrer le titre de la carte...',
|
||||
enterDescription: 'Entrez la description...',
|
||||
enterFilename: 'Entrez le nom du fichier',
|
||||
enterListTitle: 'Entrer le titre de la liste...',
|
||||
enterCardTitle: 'Saisir le titre de la carte... [Ctrl+Enter] pour ouvrir automatiquement',
|
||||
enterDescription: 'Saisir la description...',
|
||||
enterFilename: 'Saisir le nom du fichier',
|
||||
enterListTitle: 'Saisie le titre de la liste...',
|
||||
enterProjectTitle: 'Saisir le titre du projet',
|
||||
enterTaskDescription: 'Saisir la description de la tâche...',
|
||||
filterByLabels_title: 'Filtrer par libellés',
|
||||
filterByLabels_title: 'Filtrer par étiquettes',
|
||||
filterByMembers_title: 'Filtrer par membres',
|
||||
fromComputer_title: "Depuis l'ordinateur",
|
||||
hours: 'Les heures',
|
||||
fromTrello: 'Depuis Trello',
|
||||
general: 'Général',
|
||||
hours: 'Heures',
|
||||
importBoard_title: 'Importer un tableau',
|
||||
invalidCurrentPassword: 'Mot de passe actuel invalide',
|
||||
labels: 'Étiquettes',
|
||||
language: 'Langue',
|
||||
leaveBoard_title: 'Quitter le tableau',
|
||||
leaveProject_title: 'Quitter le projet',
|
||||
linkIsCopied: 'Le lien est copié',
|
||||
list: 'Lister',
|
||||
listActions_title: 'Liste des actions',
|
||||
managers: 'Managers',
|
||||
managerActions_title: 'Actions des managers',
|
||||
members: 'Membres',
|
||||
memberActions_title: 'Actions des membres',
|
||||
minutes: 'Minutes',
|
||||
moveCard_title: 'Déplacer la carte',
|
||||
name: 'Nom',
|
||||
newEmail: 'Nouveau courriel',
|
||||
newestFirst: 'Le plus récent en premier',
|
||||
newEmail: 'Nouveau email',
|
||||
newPassword: 'Nouveau mot de passe',
|
||||
newUsername: "Nouveau nom d'utilisateur",
|
||||
noConnectionToServer: 'Pas de connexion au serveur',
|
||||
noBoards: 'Pas de planches',
|
||||
noBoards: 'Pas de tableau',
|
||||
noLists: 'Pas de listes',
|
||||
noProjects: 'Pas de projets',
|
||||
notifications: 'Notifications',
|
||||
noUnreadNotifications: 'Aucune notification non lue.',
|
||||
openBoard_title: 'Open Board',
|
||||
oldestFirst: 'Le plus ancien en premier',
|
||||
openBoard_title: 'Ouvrir le tableau',
|
||||
optional_inline: 'optionnel',
|
||||
organization: 'Organisation',
|
||||
phone: 'Téléphone',
|
||||
preferences: 'Préférences',
|
||||
pressPasteShortcutToAddAttachmentFromClipboard: 'Conseil',
|
||||
pressPasteShortcutToAddAttachmentFromClipboard:
|
||||
'Conseil: appuyer sur Ctrl-V (Cmd-V sur Mac) pour ajouter une pièce jointe depuis le presse-papiers',
|
||||
project: 'Projet',
|
||||
projectNotFound_title: 'Projet introuvable',
|
||||
removeManager_title: 'Supprimer le manager',
|
||||
removeMember_title: 'Supprimer le membre',
|
||||
searchLabels: 'Chercher une étiquette...',
|
||||
searchMembers: 'Chercher un membre...',
|
||||
searchUsers: 'Chercher un utilisateur...',
|
||||
searchCards: 'Chercher une carte...',
|
||||
seconds: 'Secondes',
|
||||
selectBoard: 'Sélectionner une carte',
|
||||
selectBoard: 'Sélectionner un tableau',
|
||||
selectList: 'Sélectionner une liste',
|
||||
selectPermissions_title: 'Sélectionner les permissions',
|
||||
selectProject: 'Sélectionner un projet',
|
||||
settings: 'Réglages',
|
||||
sortList_title: 'Trier la liste',
|
||||
stopwatch: 'Minuteur',
|
||||
subscribeToMyOwnCardsByDefault: 'Abonnez-vous à mes propres cartes par défaut',
|
||||
taskActions_title: 'Actions de tâche',
|
||||
tasks: 'Tâches',
|
||||
thereIsNoPreviewAvailableForThisAttachment:
|
||||
"Il n'y a pas de prévisualisation de disponible pour cette pièce jointe.",
|
||||
time: 'Temps',
|
||||
title: 'Titre',
|
||||
userActions_title: "Actions de l'utilisateur",
|
||||
@@ -137,6 +172,8 @@ export default {
|
||||
username: "Nom d'utilisateur",
|
||||
usernameAlreadyInUse: "Nom d'utilisateur déjà utilisé",
|
||||
users: 'Utilisateurs',
|
||||
version: 'Version',
|
||||
viewer: 'Spectateur',
|
||||
writeComment: 'Écrire un commentaire...',
|
||||
},
|
||||
|
||||
@@ -148,10 +185,12 @@ export default {
|
||||
addCard_title: 'Ajouter une carte',
|
||||
addComment: 'Ajouter un commentaire',
|
||||
addList: 'Ajouter la liste',
|
||||
addMember: 'Ajouter un membre',
|
||||
addMoreDetailedDescription: 'Ajouter une description plus détaillée',
|
||||
addTask: 'Ajouter une tâche',
|
||||
addToCard: 'Ajouter à la carte',
|
||||
addUser: 'Ajouter un utilisateur',
|
||||
copyLink_title: 'Copier le lien',
|
||||
createBoard: 'Créer un tableau',
|
||||
createFile: 'Créer un fichier',
|
||||
createLabel: 'Créer une étiquette',
|
||||
@@ -174,14 +213,21 @@ export default {
|
||||
deleteTask_title: 'Supprimer la tâche',
|
||||
deleteUser: "Supprimer l'utilisateur",
|
||||
duplicate: 'Dupliquer',
|
||||
duplicateCard_title: 'Dupliquer la carte',
|
||||
edit: 'Modifier',
|
||||
editDueDate_title: "Modifier la date d'échéance",
|
||||
editDescription_title: 'Éditer la description',
|
||||
editEmail_title: "Modifier l'e-mail",
|
||||
editDescription_title: 'Modifier la description',
|
||||
editEmail_title: "Modifier l'email",
|
||||
editInformation_title: 'Modifier les informations',
|
||||
editPassword_title: 'Modifier le mot de passe',
|
||||
editPermissions: 'Modifier les permissions',
|
||||
editStopwatch_title: 'Modifier la minuterie',
|
||||
editTitle_title: 'Modifier le titre',
|
||||
editUsername_title: "Modifier le nom d'utilisateur",
|
||||
hideDetails: 'Cacher les détails',
|
||||
import: 'Importer',
|
||||
leaveBoard: 'Quitter le tableau',
|
||||
leaveProject: 'Quitter le projet',
|
||||
logOut_title: 'Se déconnecter',
|
||||
makeCover_title: 'Faire la jaquette',
|
||||
move: 'Déplacer',
|
||||
@@ -189,11 +235,15 @@ export default {
|
||||
remove: 'Supprimer',
|
||||
removeBackground: "Supprimer l'arrière-plan",
|
||||
removeCover_title: 'Supprimer la jaquette',
|
||||
removeFromBoard: 'Supprimer le tableau',
|
||||
removeFromProject: 'Supprimer du projet',
|
||||
removeManager: 'Supprimer le manager',
|
||||
removeMember: 'Supprimer le membre',
|
||||
save: 'Sauvegarder',
|
||||
showAllAttachments: 'Afficher toutes les pièces jointes ({{hidden}} masquées)',
|
||||
showDetails: 'Afficher les détails',
|
||||
showFewerAttachments: 'Afficher moins de pièces jointes',
|
||||
sortList_title: 'Trier la liste',
|
||||
start: 'Début',
|
||||
stop: 'Arrêter',
|
||||
subscribe: "S'abonner",
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
common: {
|
||||
emailOrUsername: "Email ou nom d'utilisateur",
|
||||
invalidEmailOrUsername: "Email ou nom d'utilisateur invalide",
|
||||
invalidCredentials: 'Identifiants invalides',
|
||||
invalidPassword: 'Mot de passe invalide',
|
||||
logInToPlanka: 'Se connecter à Planka',
|
||||
noInternetConnection: 'Aucune connection internet',
|
||||
@@ -11,10 +12,12 @@ export default {
|
||||
projectManagement: 'Gestion de projet',
|
||||
serverConnectionFailed: 'Connection au serveur échouée',
|
||||
unknownError: 'Erreur inconnue, réessayez plus tard',
|
||||
useSingleSignOn: "Utiliser l'authentification unique",
|
||||
},
|
||||
|
||||
action: {
|
||||
logIn: 'Se connecter',
|
||||
logInWithSSO: "Se connecter avec l'authentification unique",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -22,6 +22,7 @@ import trTR from './tr-TR';
|
||||
import ukUA from './uk-UA';
|
||||
import uzUZ from './uz-UZ';
|
||||
import zhCN from './zh-CN';
|
||||
import zhTW from './zh-TW';
|
||||
|
||||
const locales = [
|
||||
bgBG,
|
||||
@@ -48,6 +49,7 @@ const locales = [
|
||||
ukUA,
|
||||
uzUZ,
|
||||
zhCN,
|
||||
zhTW,
|
||||
];
|
||||
|
||||
export default locales;
|
||||
|
||||
@@ -180,6 +180,7 @@ export default {
|
||||
addAnotherCard: 'Добавить еще одну карточку',
|
||||
addAnotherList: 'Добавить еще один список',
|
||||
addAnotherTask: 'Добавить еще одну задачу',
|
||||
addCard: 'Добавить карточку',
|
||||
addCard_title: 'Добавить карточку',
|
||||
addComment: 'Добавить комментарий',
|
||||
addList: 'Добавить список',
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
import dateFns from 'date-fns/locale/zh-TW';
|
||||
|
||||
export default {
|
||||
dateFns,
|
||||
|
||||
format: {
|
||||
date: 'M/d/yyyy',
|
||||
time: 'p',
|
||||
dateTime: '$t(format:date) $t(format:time)',
|
||||
longDate: 'MMM d',
|
||||
longDateTime: "MMMM d 'at' p",
|
||||
fullDate: 'MMM d, y',
|
||||
fullDateTime: "MMMM d, y 'at' p",
|
||||
},
|
||||
|
||||
translation: {
|
||||
common: {
|
||||
aboutPlanka: '關於 Planka',
|
||||
account: '帳號',
|
||||
actions: '操作',
|
||||
addAttachment_title: '添加附件',
|
||||
addComment: '添加評論',
|
||||
addManager_title: '添加管理員',
|
||||
addMember_title: '添加成員',
|
||||
addUser_title: '添加使用者',
|
||||
administrator: '管理員',
|
||||
all: '全部',
|
||||
allChangesWillBeAutomaticallySavedAfterConnectionRestored: '所有修改會在重新連線後自動保存',
|
||||
areYouSureYouWantToDeleteThisAttachment: '確認刪除此附件嗎?',
|
||||
areYouSureYouWantToDeleteThisBoard: '確認刪除此看板嗎?',
|
||||
areYouSureYouWantToDeleteThisCard: '確認刪除此卡片嗎?',
|
||||
areYouSureYouWantToDeleteThisComment: '確認刪除此評論嗎?',
|
||||
areYouSureYouWantToDeleteThisLabel: '確認刪除此標籤嗎?',
|
||||
areYouSureYouWantToDeleteThisList: '確認刪除此列表嗎?',
|
||||
areYouSureYouWantToDeleteThisProject: '確認刪除此專案嗎?',
|
||||
areYouSureYouWantToDeleteThisTask: '確認刪除此任務嗎?',
|
||||
areYouSureYouWantToDeleteThisUser: '確認刪除此使用者嗎?',
|
||||
areYouSureYouWantToLeaveBoard: '確認離開此看板嗎?',
|
||||
areYouSureYouWantToLeaveProject: '確認離開此專案嗎?',
|
||||
areYouSureYouWantToRemoveThisManagerFromProject: '確認從此專案中刪除該管理員嗎?',
|
||||
areYouSureYouWantToRemoveThisMemberFromBoard: '確認從此看板中刪除該成員嗎?',
|
||||
attachment: '附件',
|
||||
attachments: '附件',
|
||||
authentication: '驗證',
|
||||
background: '背景',
|
||||
board: '看板',
|
||||
boardNotFound_title: '看板不存在',
|
||||
canComment: '可以評論',
|
||||
canEditContentOfBoard: '可以編輯看板內容',
|
||||
canOnlyViewBoard: '僅可查看看板',
|
||||
cardActions_title: '卡片操作',
|
||||
cardNotFound_title: '卡片不存在',
|
||||
cardOrActionAreDeleted: '卡片或操作已經被刪除',
|
||||
color: '顏色',
|
||||
createBoard_title: '創建看板',
|
||||
createLabel_title: '創建標籤',
|
||||
createNewOneOrSelectExistingOne: '創建一個新的或選擇一個已創建的',
|
||||
createProject_title: '創建專案',
|
||||
createTextFile_title: '創建文本文件',
|
||||
currentPassword: '當前密碼',
|
||||
dangerZone_title: '危險區域',
|
||||
date: '日期',
|
||||
dueDate_title: '截止日期',
|
||||
deleteAttachment_title: '刪除附件',
|
||||
deleteBoard_title: '刪除看板',
|
||||
deleteCard_title: '刪除卡片',
|
||||
deleteComment_title: '刪除評論',
|
||||
deleteLabel_title: '刪除標籤',
|
||||
deleteList_title: '刪除列表',
|
||||
deleteProject_title: '刪除專案',
|
||||
deleteTask_title: '刪除任務',
|
||||
deleteUser_title: '刪除使用者',
|
||||
description: '描述',
|
||||
detectAutomatically: '自動偵測',
|
||||
dropFileToUpload: '拖放文件以上傳',
|
||||
editor: '編輯器',
|
||||
editAttachment_title: '編輯附件',
|
||||
editAvatar_title: '編輯頭像',
|
||||
editBoard_title: '編輯看板',
|
||||
editDueDate_title: '編輯截止時間',
|
||||
editEmail_title: '編輯郵箱',
|
||||
editInformation_title: '編輯信息',
|
||||
editLabel_title: '編輯標籤',
|
||||
editPassword_title: '修改密碼',
|
||||
editPermissions_title: '修改權限',
|
||||
editStopwatch_title: '修改計時',
|
||||
editUsername_title: '修改使用者名稱',
|
||||
email: '郵箱',
|
||||
emailAlreadyInUse: '郵箱已被使用',
|
||||
enterCardTitle: '輸入卡片標題...',
|
||||
enterDescription: '輸入描述...',
|
||||
enterFilename: '輸入文件名',
|
||||
enterListTitle: '輸入列表標題...',
|
||||
enterProjectTitle: '輸入專案標題',
|
||||
enterTaskDescription: '輸入任務描述...',
|
||||
filterByLabels_title: '通過標籤篩選',
|
||||
filterByMembers_title: '通過成員篩選',
|
||||
fromComputer_title: '來自電腦',
|
||||
fromTrello: '來自 Trello',
|
||||
general: '通用',
|
||||
hours: '小時',
|
||||
importBoard_title: '導入看板',
|
||||
invalidCurrentPassword: '當前密碼錯誤',
|
||||
labels: '標籤',
|
||||
language: '語言',
|
||||
leaveBoard_title: '離開看板',
|
||||
leaveProject_title: '離開專案',
|
||||
list: '列表',
|
||||
listActions_title: '列表操作',
|
||||
managers: '管理員',
|
||||
members: '成員',
|
||||
minutes: '分鐘',
|
||||
moveCard_title: '移動卡片',
|
||||
name: '姓名',
|
||||
newEmail: '新郵箱',
|
||||
newPassword: '新密碼',
|
||||
newUsername: '新使用者名稱',
|
||||
noConnectionToServer: '未連接到伺服器',
|
||||
noBoards: '沒有看板',
|
||||
noLists: '沒有列表',
|
||||
noProjects: '沒有專案',
|
||||
notifications: '通知',
|
||||
noUnreadNotifications: '沒有未讀通知',
|
||||
openBoard_title: '打開看板',
|
||||
optional_inline: '可選的',
|
||||
organization: '組織機構',
|
||||
phone: '電話',
|
||||
preferences: '偏好設定',
|
||||
pressPasteShortcutToAddAttachmentFromClipboard:
|
||||
'提示: 按下 Ctrl-V (Mac: Cmd-V) 從剪貼簿添加附件',
|
||||
project: '專案',
|
||||
projectNotFound_title: '專案未找到',
|
||||
removeManager_title: '刪除管理員',
|
||||
removeMember_title: '刪除成員',
|
||||
searchLabels: '搜尋標籤...',
|
||||
searchMembers: '搜尋成員...',
|
||||
searchUsers: '搜尋使用者...',
|
||||
seconds: '秒',
|
||||
selectBoard: '選擇看板',
|
||||
selectList: '選擇列表',
|
||||
selectPermissions_title: '選擇權限',
|
||||
selectProject: '選擇專案',
|
||||
settings: '設置',
|
||||
stopwatch: '碼表',
|
||||
subscribeToMyOwnCardsByDefault: '默認訂閱自己創建的卡片',
|
||||
taskActions_title: '任務操作',
|
||||
tasks: '任務',
|
||||
thereIsNoPreviewAvailableForThisAttachment: '此附件無法預覽',
|
||||
time: '時間',
|
||||
title: '標題',
|
||||
userActions_title: '使用者操作',
|
||||
userAddedThisCardToList: '<0>{{user}}</0><1> 向列表 {{list}} 添加了該卡片</1>',
|
||||
userLeftNewCommentToCard: '{{user}} 給 {{card}} 添加了一條新評論 「{{comment}}」',
|
||||
userMovedCardFromListToList:
|
||||
'{{user}} 將卡片 <2>{{card}}</2> 從 {{fromList}} 移動到 {{toList}}',
|
||||
userMovedThisCardFromListToList:
|
||||
'<0>{{user}}</0><1> 將該卡片從 {{fromList}} 移動到 {{toList}}</1>',
|
||||
username: '使用者名稱',
|
||||
usernameAlreadyInUse: '使用者名稱已被佔用',
|
||||
users: '使用者',
|
||||
version: '版本',
|
||||
viewer: '檢視',
|
||||
writeComment: '編寫評論...',
|
||||
},
|
||||
|
||||
action: {
|
||||
addAnotherCard: '添加另一個卡片',
|
||||
addAnotherList: '添加另一個列表',
|
||||
addAnotherTask: '添加另一個任務',
|
||||
addCard: '添加卡片',
|
||||
addCard_title: '添加卡片',
|
||||
addComment: '添加評論',
|
||||
addList: '添加列表',
|
||||
addMember: '添加成員',
|
||||
addMoreDetailedDescription: '添加更多詳細描述',
|
||||
addTask: '添加任務',
|
||||
addToCard: '添加到卡片',
|
||||
addUser: '添加使用者',
|
||||
createBoard: '創建看板',
|
||||
createFile: '創建文件',
|
||||
createLabel: '創建標籤',
|
||||
createNewLabel: '創建新標籤',
|
||||
createProject: '創建專案',
|
||||
delete: '刪除',
|
||||
deleteAttachment: '刪除附件',
|
||||
deleteAvatar: '刪除頭像',
|
||||
deleteBoard: '刪除看板',
|
||||
deleteCard: '刪除卡片',
|
||||
deleteCard_title: '刪除卡片',
|
||||
deleteComment: '刪除評論',
|
||||
deleteImage: '刪除圖片',
|
||||
deleteLabel: '刪除標籤',
|
||||
deleteList: '刪除列表',
|
||||
deleteList_title: '刪除列表',
|
||||
deleteProject: '刪除專案',
|
||||
deleteProject_title: '刪除專案',
|
||||
deleteTask: '刪除任務',
|
||||
deleteTask_title: '刪除任務',
|
||||
deleteUser: '刪除使用者',
|
||||
edit: '編輯',
|
||||
editDueDate_title: '編輯截止時間',
|
||||
editDescription_title: '編輯描述',
|
||||
editEmail_title: '編輯郵箱',
|
||||
editInformation_title: '編輯信息',
|
||||
editPassword_title: '編輯密碼',
|
||||
editPermissions: '編輯權限',
|
||||
editStopwatch_title: '編輯碼表',
|
||||
editTitle_title: '編輯標題',
|
||||
editUsername_title: '編輯使用者名稱',
|
||||
hideDetails: '隱藏詳情',
|
||||
import: '導入',
|
||||
leaveBoard: '離開看板',
|
||||
leaveProject: '離開專案',
|
||||
logOut_title: '登出',
|
||||
makeCover_title: '設置封面',
|
||||
move: '移動',
|
||||
moveCard_title: '移動卡片',
|
||||
remove: '刪除',
|
||||
removeBackground: '刪除背景',
|
||||
removeCover_title: '刪除封面',
|
||||
removeFromBoard: '從看板中刪除',
|
||||
removeFromProject: '從專案中刪除',
|
||||
removeManager: '刪除管理員',
|
||||
removeMember: '刪除成員',
|
||||
save: '保存',
|
||||
showAllAttachments: '顯示所有附件 ({{hidden}} 隱藏)',
|
||||
showDetails: '顯示詳情',
|
||||
showFewerAttachments: '顯示較少附件',
|
||||
start: '開始',
|
||||
stop: '結束',
|
||||
subscribe: '訂閱',
|
||||
unsubscribe: '取消訂閱',
|
||||
uploadNewAvatar: '上傳新頭像',
|
||||
uploadNewImage: '上傳圖片',
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import login from './login';
|
||||
|
||||
export default {
|
||||
language: 'zh-TW',
|
||||
country: 'tw',
|
||||
name: '繁體中文',
|
||||
embeddedLocale: login,
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
export default {
|
||||
translation: {
|
||||
common: {
|
||||
emailOrUsername: '郵箱或使用者名稱',
|
||||
invalidEmailOrUsername: '無效的郵箱或使用者名稱',
|
||||
invalidPassword: '密碼錯誤',
|
||||
logInToPlanka: '登入至 Planka',
|
||||
noInternetConnection: '沒有網路連接',
|
||||
pageNotFound_title: '找不到頁面',
|
||||
password: '密碼',
|
||||
projectManagement: '專案管理',
|
||||
serverConnectionFailed: '伺服器連接失敗',
|
||||
unknownError: '未知錯誤,請稍後重試',
|
||||
useSingleSignOn: '使用單一登入',
|
||||
},
|
||||
|
||||
action: {
|
||||
logIn: '登入',
|
||||
logInWithSSO: '使用SSO登入',
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -6,8 +6,8 @@
|
||||
border: 0;
|
||||
color: #444444;
|
||||
font-size: 14px;
|
||||
font-family: "Museo Sans", "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
font-weight: 400;
|
||||
font-family: "Nunitoga", "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
// font-weight: 400;
|
||||
width: 100%;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
.react-datepicker__current-month,
|
||||
.react-datepicker-time__header {
|
||||
color: #444;
|
||||
font-weight: 500;
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
line-height: 32px;
|
||||
padding-bottom: 4px;
|
||||
@@ -38,7 +38,7 @@
|
||||
color: #444;
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
font-weight: 500;
|
||||
font-weight: normal;
|
||||
line-height: 28px;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export default '1.22.0';
|
||||
@@ -0,0 +1 @@
|
||||
export default '<%= pkg.version %>';
|
||||
@@ -24,6 +24,8 @@ services:
|
||||
# Configure knex to accept SSL certificates
|
||||
# - KNEX_REJECT_UNAUTHORIZED_SSL_CERTIFICATE=false
|
||||
|
||||
# - SHOW_DETAILED_AUTH_ERRORS=false # Set to true to show more detailed authentication error messages. It should not be enabled without a rate limiter for security reasons.
|
||||
|
||||
# - ALLOW_ALL_TO_CREATE_PROJECTS=true
|
||||
|
||||
# - OIDC_ISSUER=
|
||||
|
||||
@@ -31,6 +31,8 @@ services:
|
||||
# - DEFAULT_ADMIN_NAME=Demo Demo
|
||||
# - DEFAULT_ADMIN_USERNAME=demo
|
||||
|
||||
# - SHOW_DETAILED_AUTH_ERRORS=false # Set to true to show more detailed authentication error messages. It should not be enabled without a rate limiter for security reasons.
|
||||
|
||||
# - ALLOW_ALL_TO_CREATE_PROJECTS=true
|
||||
|
||||
# - OIDC_ISSUER=
|
||||
@@ -70,6 +72,7 @@ services:
|
||||
|
||||
# - SLACK_BOT_TOKEN=
|
||||
# - SLACK_CHANNEL_ID=
|
||||
# - GOOGLE_CHAT_WEBHOOK_URL=
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
||||
Generated
+259
-137
@@ -1,30 +1,31 @@
|
||||
{
|
||||
"name": "planka",
|
||||
"version": "1.21.0",
|
||||
"version": "1.22.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "planka",
|
||||
"version": "1.21.0",
|
||||
"version": "1.22.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"concurrently": "^8.2.2",
|
||||
"husky": "^9.0.1",
|
||||
"lint-staged": "^15.2.5"
|
||||
"genversion": "^3.2.0",
|
||||
"husky": "^9.1.6",
|
||||
"lint-staged": "^15.2.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"prettier": "^3.3.0"
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"prettier": "^3.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.24.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.6.tgz",
|
||||
"integrity": "sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==",
|
||||
"version": "7.25.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz",
|
||||
"integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.14.0"
|
||||
},
|
||||
@@ -48,9 +49,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint-community/regexpp": {
|
||||
"version": "4.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
|
||||
"integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
|
||||
"version": "4.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz",
|
||||
"integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||
@@ -92,6 +93,7 @@
|
||||
"version": "0.11.14",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
|
||||
"integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
|
||||
"deprecated": "Use @eslint/config-array instead",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@humanwhocodes/object-schema": "^2.0.2",
|
||||
@@ -119,6 +121,7 @@
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
|
||||
"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
|
||||
"deprecated": "Use @eslint/object-schema instead",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
@@ -175,9 +178,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.11.3",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
|
||||
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
|
||||
"version": "8.12.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
|
||||
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
@@ -212,11 +215,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-escapes": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz",
|
||||
"integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==",
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz",
|
||||
"integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==",
|
||||
"dependencies": {
|
||||
"environment": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
@@ -250,17 +256,20 @@
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/async": {
|
||||
"version": "3.2.6",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
|
||||
"integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@@ -313,14 +322,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/cli-cursor": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
|
||||
"integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
|
||||
"integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==",
|
||||
"dependencies": {
|
||||
"restore-cursor": "^4.0.0"
|
||||
"restore-cursor": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
@@ -418,18 +427,17 @@
|
||||
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "12.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
||||
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/concurrently": {
|
||||
"version": "8.2.2",
|
||||
@@ -486,11 +494,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.5",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
|
||||
"integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
||||
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
@@ -519,15 +527,40 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ejs": {
|
||||
"version": "3.1.10",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
|
||||
"integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
|
||||
"dependencies": {
|
||||
"jake": "^10.8.5"
|
||||
},
|
||||
"bin": {
|
||||
"ejs": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "10.3.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz",
|
||||
"integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw=="
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
|
||||
"integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="
|
||||
},
|
||||
"node_modules/environment": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz",
|
||||
"integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
|
||||
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
|
||||
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@@ -612,13 +645,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-prettier": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz",
|
||||
"integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==",
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz",
|
||||
"integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"prettier-linter-helpers": "^1.0.0",
|
||||
"synckit": "^0.8.6"
|
||||
"synckit": "^0.9.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
@@ -687,9 +720,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esquery": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
|
||||
"integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
|
||||
"integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"estraverse": "^5.1.0"
|
||||
@@ -800,6 +833,33 @@
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/filelist": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
|
||||
"integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
|
||||
"dependencies": {
|
||||
"minimatch": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/filelist/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/filelist/node_modules/minimatch": {
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
|
||||
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
@@ -811,6 +871,14 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/find-package": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-package/-/find-package-1.0.0.tgz",
|
||||
"integrity": "sha512-yVn71XCCaNgxz58ERTl8nA/8YYtIQDY9mHSrgFBfiFtdNNfY0h183Vh8BRkKxD8x9TUw3ec290uJKhDVxqGZBw==",
|
||||
"dependencies": {
|
||||
"parents": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/find-up": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
|
||||
@@ -853,6 +921,22 @@
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/genversion": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/genversion/-/genversion-3.2.0.tgz",
|
||||
"integrity": "sha512-OIYSX6XYA8PHecLDCTri30hadSZfAjZ8Iq1+BBDXqLWP4dRLuJNLoNjsSWtTpw97IccK2LDWzkEstxAB8GdN7g==",
|
||||
"dependencies": {
|
||||
"commander": "^7.2.0",
|
||||
"ejs": "^3.1.9",
|
||||
"find-package": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"genversion": "bin/genversion.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
@@ -954,11 +1038,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/husky": {
|
||||
"version": "9.0.11",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz",
|
||||
"integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==",
|
||||
"version": "9.1.6",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz",
|
||||
"integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==",
|
||||
"bin": {
|
||||
"husky": "bin.mjs"
|
||||
"husky": "bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -968,9 +1052,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
|
||||
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
@@ -1083,6 +1167,23 @@
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
||||
},
|
||||
"node_modules/jake": {
|
||||
"version": "10.9.2",
|
||||
"resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz",
|
||||
"integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==",
|
||||
"dependencies": {
|
||||
"async": "^3.2.3",
|
||||
"chalk": "^4.0.2",
|
||||
"filelist": "^1.0.4",
|
||||
"minimatch": "^3.1.2"
|
||||
},
|
||||
"bin": {
|
||||
"jake": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
@@ -1136,9 +1237,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/lilconfig": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz",
|
||||
"integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==",
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
|
||||
"integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
@@ -1147,20 +1248,20 @@
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged": {
|
||||
"version": "15.2.5",
|
||||
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.5.tgz",
|
||||
"integrity": "sha512-j+DfX7W9YUvdzEZl3Rk47FhDF6xwDBV5wwsCPw6BwWZVPYJemusQmvb9bRsW23Sqsaa+vRloAWogbK4BUuU2zA==",
|
||||
"version": "15.2.10",
|
||||
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz",
|
||||
"integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==",
|
||||
"dependencies": {
|
||||
"chalk": "~5.3.0",
|
||||
"commander": "~12.1.0",
|
||||
"debug": "~4.3.4",
|
||||
"debug": "~4.3.6",
|
||||
"execa": "~8.0.1",
|
||||
"lilconfig": "~3.1.1",
|
||||
"listr2": "~8.2.1",
|
||||
"micromatch": "~4.0.7",
|
||||
"lilconfig": "~3.1.2",
|
||||
"listr2": "~8.2.4",
|
||||
"micromatch": "~4.0.8",
|
||||
"pidtree": "~0.6.0",
|
||||
"string-argv": "~0.3.2",
|
||||
"yaml": "~2.4.2"
|
||||
"yaml": "~2.5.0"
|
||||
},
|
||||
"bin": {
|
||||
"lint-staged": "bin/lint-staged.js"
|
||||
@@ -1183,16 +1284,24 @@
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/commander": {
|
||||
"version": "12.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
||||
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/listr2": {
|
||||
"version": "8.2.1",
|
||||
"resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.1.tgz",
|
||||
"integrity": "sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==",
|
||||
"version": "8.2.4",
|
||||
"resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.4.tgz",
|
||||
"integrity": "sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==",
|
||||
"dependencies": {
|
||||
"cli-truncate": "^4.0.0",
|
||||
"colorette": "^2.0.20",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"log-update": "^6.0.0",
|
||||
"rfdc": "^1.3.1",
|
||||
"log-update": "^6.1.0",
|
||||
"rfdc": "^1.4.1",
|
||||
"wrap-ansi": "^9.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -1226,13 +1335,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/log-update": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz",
|
||||
"integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==",
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz",
|
||||
"integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==",
|
||||
"dependencies": {
|
||||
"ansi-escapes": "^6.2.0",
|
||||
"cli-cursor": "^4.0.0",
|
||||
"slice-ansi": "^7.0.0",
|
||||
"ansi-escapes": "^7.0.0",
|
||||
"cli-cursor": "^5.0.0",
|
||||
"slice-ansi": "^7.1.0",
|
||||
"strip-ansi": "^7.1.0",
|
||||
"wrap-ansi": "^9.0.0"
|
||||
},
|
||||
@@ -1244,9 +1353,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/node_modules/ansi-regex": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
|
||||
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -1314,9 +1423,9 @@
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
|
||||
"integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||
"dependencies": {
|
||||
"braces": "^3.0.3",
|
||||
"picomatch": "^2.3.1"
|
||||
@@ -1336,11 +1445,21 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/mimic-function": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
|
||||
"integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
@@ -1349,9 +1468,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"node_modules/natural-compare": {
|
||||
"version": "1.4.0",
|
||||
@@ -1466,6 +1585,14 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/parents": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz",
|
||||
"integrity": "sha512-mXKF3xkoUt5td2DoxpLmtOmZvko9VfFpwRwkKDHSNvgmpLAeBo18YDhcPbBzJq+QLCHMbGOfzia2cX4U+0v9Mg==",
|
||||
"dependencies": {
|
||||
"path-platform": "~0.11.15"
|
||||
}
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
@@ -1492,6 +1619,14 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-platform": {
|
||||
"version": "0.11.15",
|
||||
"resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz",
|
||||
"integrity": "sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg==",
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
@@ -1524,9 +1659,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.0.tgz",
|
||||
"integrity": "sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g==",
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
|
||||
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
@@ -1602,47 +1737,34 @@
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
|
||||
"integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz",
|
||||
"integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==",
|
||||
"dependencies": {
|
||||
"onetime": "^5.1.0",
|
||||
"signal-exit": "^3.0.2"
|
||||
"onetime": "^7.0.0",
|
||||
"signal-exit": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor/node_modules/mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor/node_modules/onetime": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz",
|
||||
"integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==",
|
||||
"dependencies": {
|
||||
"mimic-fn": "^2.1.0"
|
||||
"mimic-function": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor/node_modules/signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
||||
},
|
||||
"node_modules/reusify": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||
@@ -1654,9 +1776,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rfdc": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz",
|
||||
"integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg=="
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
|
||||
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
@@ -1783,9 +1905,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz",
|
||||
"integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==",
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
|
||||
"integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^10.3.0",
|
||||
"get-east-asian-width": "^1.0.0",
|
||||
@@ -1799,9 +1921,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/string-width/node_modules/ansi-regex": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
|
||||
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -1872,9 +1994,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/synckit": {
|
||||
"version": "0.8.8",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz",
|
||||
"integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==",
|
||||
"version": "0.9.1",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz",
|
||||
"integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@pkgr/core": "^0.1.0",
|
||||
@@ -1913,9 +2035,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
|
||||
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
@@ -1990,9 +2112,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi/node_modules/ansi-regex": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
|
||||
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -2040,9 +2162,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz",
|
||||
"integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==",
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz",
|
||||
"integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==",
|
||||
"bin": {
|
||||
"yaml": "bin.mjs"
|
||||
},
|
||||
|
||||
+7
-5
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "planka",
|
||||
"version": "1.21.0",
|
||||
"version": "1.22.0",
|
||||
"private": true,
|
||||
"homepage": "https://plankanban.github.io/planka",
|
||||
"repository": {
|
||||
@@ -16,6 +16,7 @@
|
||||
"client:test": "npm test --prefix client",
|
||||
"docker:build": "docker build -t ghcr.io/plankanban/planka:local -f Dockerfile .",
|
||||
"docker:build:base": "docker build -t ghcr.io/plankanban/planka:base-local -f Dockerfile.base .",
|
||||
"gv": "genversion --source ./ --template client/version-template.ejs client/src/version.js",
|
||||
"postinstall": "(cd server && npm i && cd ../client && npm i)",
|
||||
"lint": "npm run server:lint && npm run client:lint",
|
||||
"prepare": "husky",
|
||||
@@ -57,13 +58,14 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"concurrently": "^8.2.2",
|
||||
"husky": "^9.0.1",
|
||||
"lint-staged": "^15.2.5"
|
||||
"genversion": "^3.2.0",
|
||||
"husky": "^9.1.6",
|
||||
"lint-staged": "^15.2.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"prettier": "^3.3.0"
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"prettier": "^3.3.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ SECRET_KEY=notsecretkey
|
||||
# DEFAULT_ADMIN_NAME=Demo Demo
|
||||
# DEFAULT_ADMIN_USERNAME=demo
|
||||
|
||||
# SHOW_DETAILED_AUTH_ERRORS=false # Set to true to show more detailed authentication error messages. It should not be enabled without a rate limiter for security reasons.
|
||||
|
||||
# ALLOW_ALL_TO_CREATE_PROJECTS=true
|
||||
|
||||
# OIDC_ISSUER=
|
||||
@@ -59,6 +61,7 @@ SECRET_KEY=notsecretkey
|
||||
|
||||
# SLACK_BOT_TOKEN=
|
||||
# SLACK_CHANNEL_ID=
|
||||
# GOOGLE_CHAT_WEBHOOK_URL=
|
||||
|
||||
## Do not edit this
|
||||
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
const bcrypt = require('bcrypt');
|
||||
const validator = require('validator');
|
||||
const { v4: uuid } = require('uuid');
|
||||
|
||||
const { getRemoteAddress } = require('../../../utils/remoteAddress');
|
||||
|
||||
const Errors = {
|
||||
INVALID_CREDENTIALS: {
|
||||
invalidCredentials: 'Invalid credentials',
|
||||
},
|
||||
INVALID_EMAIL_OR_USERNAME: {
|
||||
invalidEmailOrUsername: 'Invalid email or username',
|
||||
},
|
||||
@@ -31,9 +35,16 @@ module.exports = {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
withHttpOnlyToken: {
|
||||
type: 'boolean',
|
||||
defaultsTo: false,
|
||||
},
|
||||
},
|
||||
|
||||
exits: {
|
||||
invalidCredentials: {
|
||||
responseType: 'unauthorized',
|
||||
},
|
||||
invalidEmailOrUsername: {
|
||||
responseType: 'unauthorized',
|
||||
},
|
||||
@@ -57,7 +68,10 @@ module.exports = {
|
||||
sails.log.warn(
|
||||
`Invalid email or username: "${inputs.emailOrUsername}"! (IP: ${remoteAddress})`,
|
||||
);
|
||||
throw Errors.INVALID_EMAIL_OR_USERNAME;
|
||||
|
||||
throw sails.config.custom.showDetailedAuthErrors
|
||||
? Errors.INVALID_EMAIL_OR_USERNAME
|
||||
: Errors.INVALID_CREDENTIALS;
|
||||
}
|
||||
|
||||
if (user.isSso) {
|
||||
@@ -66,18 +80,30 @@ module.exports = {
|
||||
|
||||
if (!bcrypt.compareSync(inputs.password, user.password)) {
|
||||
sails.log.warn(`Invalid password! (IP: ${remoteAddress})`);
|
||||
throw Errors.INVALID_PASSWORD;
|
||||
|
||||
throw sails.config.custom.showDetailedAuthErrors
|
||||
? Errors.INVALID_PASSWORD
|
||||
: Errors.INVALID_CREDENTIALS;
|
||||
}
|
||||
|
||||
const accessToken = sails.helpers.utils.createToken(user.id);
|
||||
const { token: accessToken, payload: accessTokenPayload } = sails.helpers.utils.createJwtToken(
|
||||
user.id,
|
||||
);
|
||||
|
||||
const httpOnlyToken = inputs.withHttpOnlyToken ? uuid() : null;
|
||||
|
||||
await Session.create({
|
||||
accessToken,
|
||||
httpOnlyToken,
|
||||
remoteAddress,
|
||||
userId: user.id,
|
||||
userAgent: this.req.headers['user-agent'],
|
||||
});
|
||||
|
||||
if (httpOnlyToken && !this.req.isSocket) {
|
||||
sails.helpers.utils.setHttpOnlyTokenCookie(httpOnlyToken, accessTokenPayload, this.res);
|
||||
}
|
||||
|
||||
return {
|
||||
item: accessToken,
|
||||
};
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
module.exports = {
|
||||
async fn() {
|
||||
const { accessToken } = this.req;
|
||||
const { currentSession } = this.req;
|
||||
|
||||
await Session.updateOne({
|
||||
accessToken,
|
||||
id: currentSession.id,
|
||||
deletedAt: null,
|
||||
}).set({
|
||||
deletedAt: new Date().toISOString(),
|
||||
});
|
||||
|
||||
if (this.req.isSocket) {
|
||||
sails.sockets.leaveAll(`@accessToken:${accessToken}`);
|
||||
sails.sockets.leaveAll(`@accessToken:${currentSession.accessToken}`);
|
||||
|
||||
if (currentSession.httpOnlyToken && !this.req.isSocket) {
|
||||
sails.helpers.utils.clearHttpOnlyTokenCookie(this.res);
|
||||
}
|
||||
|
||||
return {
|
||||
item: accessToken,
|
||||
item: currentSession.accessToken,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
const { v4: uuid } = require('uuid');
|
||||
|
||||
const { getRemoteAddress } = require('../../../utils/remoteAddress');
|
||||
|
||||
const Errors = {
|
||||
@@ -28,6 +30,10 @@ module.exports = {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
withHttpOnlyToken: {
|
||||
type: 'boolean',
|
||||
defaultsTo: false,
|
||||
},
|
||||
},
|
||||
|
||||
exits: {
|
||||
@@ -62,15 +68,24 @@ module.exports = {
|
||||
.intercept('usernameAlreadyInUse', () => Errors.USERNAME_ALREADY_IN_USE)
|
||||
.intercept('missingValues', () => Errors.MISSING_VALUES);
|
||||
|
||||
const accessToken = sails.helpers.utils.createToken(user.id);
|
||||
const { token: accessToken, payload: accessTokenPayload } = sails.helpers.utils.createJwtToken(
|
||||
user.id,
|
||||
);
|
||||
|
||||
const httpOnlyToken = inputs.withHttpOnlyToken ? uuid() : null;
|
||||
|
||||
await Session.create({
|
||||
accessToken,
|
||||
httpOnlyToken,
|
||||
remoteAddress,
|
||||
userId: user.id,
|
||||
userAgent: this.req.headers['user-agent'],
|
||||
});
|
||||
|
||||
if (httpOnlyToken && !this.req.isSocket) {
|
||||
sails.helpers.utils.setHttpOnlyTokenCookie(httpOnlyToken, accessTokenPayload, this.res);
|
||||
}
|
||||
|
||||
return {
|
||||
item: accessToken,
|
||||
};
|
||||
|
||||
@@ -48,7 +48,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const { currentUser } = this.req;
|
||||
const { currentSession, currentUser } = this.req;
|
||||
|
||||
if (inputs.id === currentUser.id) {
|
||||
if (!inputs.currentPassword) {
|
||||
@@ -89,10 +89,14 @@ module.exports = {
|
||||
}
|
||||
|
||||
if (user.id === currentUser.id) {
|
||||
const accessToken = sails.helpers.utils.createToken(user.id, user.passwordUpdatedAt);
|
||||
const { token: accessToken } = sails.helpers.utils.createJwtToken(
|
||||
user.id,
|
||||
user.passwordUpdatedAt,
|
||||
);
|
||||
|
||||
await Session.create({
|
||||
accessToken,
|
||||
httpOnlyToken: currentSession.httpOnlyToken,
|
||||
userId: user.id,
|
||||
remoteAddress: getRemoteAddress(this.req),
|
||||
userAgent: this.req.headers['user-agent'],
|
||||
|
||||
@@ -14,7 +14,7 @@ const valuesValidator = (value) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
const buildAndSendSlackMessage = async (card, action, actorUser) => {
|
||||
const buildAndSendMessage = async (card, action, actorUser, send) => {
|
||||
const cardLink = `<${sails.config.custom.baseUrl}/cards/${card.id}|${card.name}>`;
|
||||
|
||||
let markdown;
|
||||
@@ -35,7 +35,7 @@ const buildAndSendSlackMessage = async (card, action, actorUser) => {
|
||||
return;
|
||||
}
|
||||
|
||||
await sails.helpers.utils.sendSlackMessage(markdown);
|
||||
await send(markdown);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
@@ -94,10 +94,6 @@ module.exports = {
|
||||
user: values.user,
|
||||
});
|
||||
|
||||
if (sails.config.custom.slackBotToken) {
|
||||
buildAndSendSlackMessage(values.card, action, values.user);
|
||||
}
|
||||
|
||||
const subscriptionUserIds = await sails.helpers.cards.getSubscriptionUserIds(
|
||||
action.cardId,
|
||||
action.userId,
|
||||
@@ -119,6 +115,18 @@ module.exports = {
|
||||
),
|
||||
);
|
||||
|
||||
if (sails.config.custom.slackBotToken) {
|
||||
buildAndSendMessage(values.card, action, values.user, sails.helpers.utils.sendSlackMessage);
|
||||
}
|
||||
|
||||
if (sails.config.custom.googleChatWebhookUrl) {
|
||||
buildAndSendMessage(
|
||||
values.card,
|
||||
action,
|
||||
values.user,
|
||||
sails.helpers.utils.sendGoogleChatMessage,
|
||||
);
|
||||
}
|
||||
return action;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,10 +2,11 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const rimraf = require('rimraf');
|
||||
const moveFile = require('move-file');
|
||||
const filenamify = require('filenamify');
|
||||
const { v4: uuid } = require('uuid');
|
||||
const sharp = require('sharp');
|
||||
|
||||
const filenamify = require('../../../utils/filenamify');
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
file: {
|
||||
@@ -17,7 +18,6 @@ module.exports = {
|
||||
async fn(inputs) {
|
||||
const dirname = uuid();
|
||||
|
||||
// FIXME: https://github.com/sindresorhus/filenamify/issues/13
|
||||
const filename = filenamify(inputs.file.filename);
|
||||
|
||||
const rootPath = path.join(sails.config.custom.attachmentsPath, dirname);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const buildAndSendSlackMessage = async (card, actorUser) => {
|
||||
await sails.helpers.utils.sendSlackMessage(`*${card.name}* was deleted by ${actorUser.name}`);
|
||||
const buildAndSendMessage = async (card, actorUser, send) => {
|
||||
await send(`*${card.name}* was deleted by ${actorUser.name}`);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
@@ -56,7 +56,11 @@ module.exports = {
|
||||
});
|
||||
|
||||
if (sails.config.custom.slackBotToken) {
|
||||
buildAndSendSlackMessage(card, inputs.actorUser);
|
||||
buildAndSendMessage(card, inputs.actorUser, sails.helpers.utils.sendSlackMessage);
|
||||
}
|
||||
|
||||
if (sails.config.custom.googleChatWebhookUrl) {
|
||||
buildAndSendMessage(card, inputs.actorUser, sails.helpers.utils.sendGoogleChatMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ module.exports = {
|
||||
|
||||
Object.assign(values, {
|
||||
password: bcrypt.hashSync(values.password, 10),
|
||||
passwordChangedAt: new Date().toISOString(),
|
||||
passwordChangedAt: new Date().toUTCString(), // FIXME: hack
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
module.exports = {
|
||||
sync: true,
|
||||
|
||||
inputs: {
|
||||
response: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
fn(inputs) {
|
||||
inputs.response.clearCookie('httpOnlyToken', {
|
||||
path: sails.config.custom.baseUrlPath,
|
||||
});
|
||||
},
|
||||
};
|
||||
+14
-9
@@ -16,18 +16,23 @@ module.exports = {
|
||||
|
||||
fn(inputs) {
|
||||
const { issuedAt = new Date() } = inputs;
|
||||
const iat = Math.floor(issuedAt / 1000);
|
||||
|
||||
return jwt.sign(
|
||||
{
|
||||
const iat = Math.floor(issuedAt / 1000);
|
||||
const exp = iat + sails.config.custom.tokenExpiresIn * 24 * 60 * 60;
|
||||
|
||||
const payload = {
|
||||
iat,
|
||||
exp,
|
||||
sub: inputs.subject,
|
||||
exp: iat + sails.config.custom.tokenExpiresIn * 24 * 60 * 60,
|
||||
},
|
||||
sails.config.session.secret,
|
||||
{
|
||||
};
|
||||
|
||||
const token = jwt.sign(payload, sails.config.session.secret, {
|
||||
keyid: uuid(),
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
token,
|
||||
payload,
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
module.exports = {
|
||||
inputs: {
|
||||
markdown: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
};
|
||||
|
||||
const body = {
|
||||
text: inputs.markdown,
|
||||
};
|
||||
|
||||
let response;
|
||||
try {
|
||||
response = await fetch(sails.config.custom.googleChatWebhookUrl, {
|
||||
headers,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
} catch (error) {
|
||||
sails.log.error(`Error sending to Google Chat: ${error}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
sails.log.error(`Error sending to Google Chat: ${response.error}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const responseJson = await response.json();
|
||||
|
||||
if (!responseJson.ok) {
|
||||
sails.log.error(`Error sending to Google Chat: ${responseJson.error}`);
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
module.exports = {
|
||||
sync: true,
|
||||
|
||||
inputs: {
|
||||
value: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
accessTokenPayload: {
|
||||
type: 'json',
|
||||
required: true,
|
||||
},
|
||||
response: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
fn(inputs) {
|
||||
inputs.response.cookie('httpOnlyToken', inputs.value, {
|
||||
expires: new Date(inputs.accessTokenPayload.exp * 1000),
|
||||
path: sails.config.custom.baseUrlPath,
|
||||
secure: sails.config.custom.baseUrlSecure,
|
||||
httpOnly: true,
|
||||
sameSite: 'strict',
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -9,10 +9,10 @@
|
||||
module.exports = function defineCurrentUserHook(sails) {
|
||||
const TOKEN_PATTERN = /^Bearer /;
|
||||
|
||||
const getUser = async (accessToken) => {
|
||||
const getSessionAndUser = async (accessToken, httpOnlyToken) => {
|
||||
let payload;
|
||||
try {
|
||||
payload = sails.helpers.utils.verifyToken(accessToken);
|
||||
payload = sails.helpers.utils.verifyJwtToken(accessToken);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
@@ -26,13 +26,20 @@ module.exports = function defineCurrentUserHook(sails) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (session.httpOnlyToken && httpOnlyToken !== session.httpOnlyToken) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const user = await sails.helpers.users.getOne(payload.subject);
|
||||
|
||||
if (user && user.passwordChangedAt > payload.issuedAt) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return user;
|
||||
return {
|
||||
session,
|
||||
user,
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
@@ -52,17 +59,21 @@ module.exports = function defineCurrentUserHook(sails) {
|
||||
|
||||
if (authorizationHeader && TOKEN_PATTERN.test(authorizationHeader)) {
|
||||
const accessToken = authorizationHeader.replace(TOKEN_PATTERN, '');
|
||||
const currentUser = await getUser(accessToken);
|
||||
const { httpOnlyToken } = req.cookies;
|
||||
|
||||
const sessionAndUser = await getSessionAndUser(accessToken, httpOnlyToken);
|
||||
|
||||
if (sessionAndUser) {
|
||||
const { session, user } = sessionAndUser;
|
||||
|
||||
if (currentUser) {
|
||||
Object.assign(req, {
|
||||
accessToken,
|
||||
currentUser,
|
||||
currentSession: session,
|
||||
currentUser: user,
|
||||
});
|
||||
|
||||
if (req.isSocket) {
|
||||
sails.sockets.join(req, `@accessToken:${accessToken}`);
|
||||
sails.sockets.join(req, `@user:${currentUser.id}`);
|
||||
sails.sockets.join(req, `@accessToken:${session.accessToken}`);
|
||||
sails.sockets.join(req, `@user:${user.id}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,15 +83,17 @@ module.exports = function defineCurrentUserHook(sails) {
|
||||
},
|
||||
'/attachments/*': {
|
||||
async fn(req, res, next) {
|
||||
const { accessToken } = req.cookies;
|
||||
const { accessToken, httpOnlyToken } = req.cookies;
|
||||
|
||||
if (accessToken) {
|
||||
const currentUser = await getUser(accessToken);
|
||||
const sessionAndUser = await getSessionAndUser(accessToken, httpOnlyToken);
|
||||
|
||||
if (sessionAndUser) {
|
||||
const { session, user } = sessionAndUser;
|
||||
|
||||
if (currentUser) {
|
||||
Object.assign(req, {
|
||||
accessToken,
|
||||
currentUser,
|
||||
currentSession: session,
|
||||
currentUser: user,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ module.exports = function defineWatcherHook(sails) {
|
||||
const accessToken = room.split(':')[1];
|
||||
|
||||
try {
|
||||
sails.helpers.utils.verifyToken(accessToken);
|
||||
sails.helpers.utils.verifyJwtToken(accessToken);
|
||||
} catch (error) {
|
||||
sails.sockets.broadcast(room, 'logout');
|
||||
sails.sockets.leaveAll(room);
|
||||
|
||||
@@ -16,6 +16,12 @@ module.exports = {
|
||||
required: true,
|
||||
columnName: 'access_token',
|
||||
},
|
||||
httpOnlyToken: {
|
||||
type: 'string',
|
||||
isNotEmptyString: true,
|
||||
allowNull: true,
|
||||
columnName: 'http_only_token',
|
||||
},
|
||||
remoteAddress: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
|
||||
@@ -30,6 +30,7 @@ const LANGUAGES = [
|
||||
'uk-UA',
|
||||
'uz-UZ',
|
||||
'zh-CN',
|
||||
'zh-TW',
|
||||
];
|
||||
|
||||
const OIDC = {
|
||||
|
||||
@@ -8,9 +8,12 @@
|
||||
* https://sailsjs.com/config/custom
|
||||
*/
|
||||
|
||||
const url = require('url');
|
||||
const path = require('path');
|
||||
const sails = require('sails');
|
||||
|
||||
const parsedBasedUrl = new url.URL(process.env.BASE_URL);
|
||||
|
||||
module.exports.custom = {
|
||||
/**
|
||||
*
|
||||
@@ -19,6 +22,8 @@ module.exports.custom = {
|
||||
*/
|
||||
|
||||
baseUrl: process.env.BASE_URL,
|
||||
baseUrlPath: parsedBasedUrl.pathname,
|
||||
baseUrlSecure: parsedBasedUrl.protocol === 'https:',
|
||||
|
||||
tokenExpiresIn: parseInt(process.env.TOKEN_EXPIRES_IN, 10) || 365,
|
||||
|
||||
@@ -34,6 +39,8 @@ module.exports.custom = {
|
||||
defaultAdminEmail:
|
||||
process.env.DEFAULT_ADMIN_EMAIL && process.env.DEFAULT_ADMIN_EMAIL.toLowerCase(),
|
||||
|
||||
showDetailedAuthErrors: process.env.SHOW_DETAILED_AUTH_ERRORS === 'true',
|
||||
|
||||
allowAllToCreateProjects: process.env.ALLOW_ALL_TO_CREATE_PROJECTS === 'true',
|
||||
|
||||
oidcIssuer: process.env.OIDC_ISSUER,
|
||||
@@ -70,4 +77,5 @@ module.exports.custom = {
|
||||
|
||||
slackBotToken: process.env.SLACK_BOT_TOKEN,
|
||||
slackChannelId: process.env.SLACK_CHANNEL_ID,
|
||||
googleChatWebhookUrl: process.env.GOOGLE_CHAT_WEBHOOK_URL,
|
||||
};
|
||||
|
||||
Vendored
+7
-4
@@ -23,6 +23,8 @@ const url = require('url');
|
||||
|
||||
const { customLogger } = require('../../utils/logger');
|
||||
|
||||
const parsedBasedUrl = new url.URL(process.env.BASE_URL);
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
*
|
||||
@@ -131,9 +133,10 @@ module.exports = {
|
||||
*/
|
||||
|
||||
cors: {
|
||||
// allowOrigins: [
|
||||
// 'https://example.com',
|
||||
// ],
|
||||
allRoutes: false,
|
||||
allowOrigins: '*',
|
||||
allowRequestHeaders: 'content-type',
|
||||
allowCredentials: false,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -218,7 +221,7 @@ module.exports = {
|
||||
*
|
||||
*/
|
||||
|
||||
onlyAllowOrigins: [new url.URL(process.env.BASE_URL).origin],
|
||||
onlyAllowOrigins: [parsedBasedUrl.origin],
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
module.exports.up = async (knex) =>
|
||||
knex.schema.table('session', (table) => {
|
||||
/* Columns */
|
||||
|
||||
table.text('http_only_token');
|
||||
});
|
||||
|
||||
module.exports.down = (knex) =>
|
||||
knex.schema.table('session', (table) => {
|
||||
table.dropColumn('http_only_token');
|
||||
});
|
||||
Generated
+7030
-7309
File diff suppressed because it is too large
Load Diff
+16
-11
@@ -8,6 +8,7 @@
|
||||
"db:migrate": "knex migrate:latest --cwd db",
|
||||
"db:seed": "knex seed:run --cwd db",
|
||||
"lint": "eslint . --max-warnings=0 --report-unused-disable-directives && echo '✔ Your .js files look good.'",
|
||||
"preinstall": "npx npm-force-resolutions",
|
||||
"start": "nodemon",
|
||||
"start:prod": "node app.js --prod",
|
||||
"test": "mocha test/lifecycle.test.js test/integration/**/*.test.js test/utils/**/*.test.js"
|
||||
@@ -30,33 +31,37 @@
|
||||
"bcrypt": "^5.1.1",
|
||||
"dotenv": "^16.4.5",
|
||||
"dotenv-cli": "^7.4.2",
|
||||
"filenamify": "^4.3.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"knex": "^3.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.30.1",
|
||||
"move-file": "^2.1.0",
|
||||
"nodemailer": "^6.9.13",
|
||||
"openid-client": "^5.6.5",
|
||||
"rimraf": "^5.0.7",
|
||||
"nodemailer": "^6.9.15",
|
||||
"openid-client": "^5.7.0",
|
||||
"rimraf": "^5.0.10",
|
||||
"sails": "^1.5.11",
|
||||
"sails-hook-orm": "^4.0.3",
|
||||
"sails-hook-sockets": "^3.0.0",
|
||||
"sails-hook-sockets": "^3.0.1",
|
||||
"sails-postgresql": "^5.0.1",
|
||||
"sharp": "^0.33.4",
|
||||
"sharp": "^0.33.5",
|
||||
"stream-to-array": "^2.3.0",
|
||||
"uuid": "^9.0.1",
|
||||
"validator": "^13.12.0",
|
||||
"winston": "^3.13.0",
|
||||
"winston": "^3.14.2",
|
||||
"zxcvbn": "^4.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.4.1",
|
||||
"chai": "^4.5.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"mocha": "^10.4.0",
|
||||
"nodemon": "^3.1.2"
|
||||
"eslint-plugin-import": "^2.30.0",
|
||||
"mocha": "^10.7.3",
|
||||
"nodemon": "^3.1.4"
|
||||
},
|
||||
"resolutions": {
|
||||
"body-parser": "1.20.3",
|
||||
"express": "4.21.0",
|
||||
"send": "0.19.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/* https://github.com/sindresorhus/filename-reserved-regex */
|
||||
|
||||
function filenameReservedRegex() {
|
||||
return /[<>:"/\\|?*\u0000-\u001F]/g; // eslint-disable-line no-control-regex
|
||||
}
|
||||
|
||||
function windowsReservedNameRegex() {
|
||||
return /^(con|prn|aux|nul|com\d|lpt\d)$/i;
|
||||
}
|
||||
|
||||
/* https://github.com/sindresorhus/filenamify */
|
||||
|
||||
// Doesn't make sense to have longer filenames
|
||||
const MAX_FILENAME_LENGTH = 100;
|
||||
|
||||
const reRelativePath = /^\.+(\\|\/)|^\.+$/;
|
||||
const reTrailingPeriods = /\.+$/;
|
||||
|
||||
function filenamify(string, options = {}) {
|
||||
const reControlChars = /[\u0000-\u001F\u0080-\u009F]/g; // eslint-disable-line no-control-regex
|
||||
const reRepeatedReservedCharacters = /([<>:"/\\|?*\u0000-\u001F]){2,}/g; // eslint-disable-line no-control-regex
|
||||
|
||||
if (typeof string !== 'string') {
|
||||
throw new TypeError('Expected a string');
|
||||
}
|
||||
|
||||
const replacement = options.replacement === undefined ? '!' : options.replacement;
|
||||
|
||||
if (filenameReservedRegex().test(replacement) && reControlChars.test(replacement)) {
|
||||
throw new Error('Replacement string cannot contain reserved filename characters');
|
||||
}
|
||||
|
||||
/* eslint-disable no-param-reassign */
|
||||
if (replacement.length > 0) {
|
||||
string = string.replace(reRepeatedReservedCharacters, '$1');
|
||||
}
|
||||
|
||||
string = string.normalize('NFD');
|
||||
string = string.replace(reRelativePath, replacement);
|
||||
string = string.replace(filenameReservedRegex(), replacement);
|
||||
string = string.replace(reControlChars, replacement);
|
||||
string = string.replace(reTrailingPeriods, '');
|
||||
|
||||
if (replacement.length > 0) {
|
||||
const startedWithDot = string[0] === '.';
|
||||
|
||||
// We removed the whole filename
|
||||
if (!startedWithDot && string[0] === '.') {
|
||||
string = replacement + string;
|
||||
}
|
||||
|
||||
// We removed the whole extension
|
||||
if (string[string.length - 1] === '.') {
|
||||
string += replacement;
|
||||
}
|
||||
}
|
||||
|
||||
string = windowsReservedNameRegex().test(string) ? string + replacement : string;
|
||||
const allowedLength =
|
||||
typeof options.maxLength === 'number' ? options.maxLength : MAX_FILENAME_LENGTH;
|
||||
if (string.length > allowedLength) {
|
||||
const extensionIndex = string.lastIndexOf('.');
|
||||
if (extensionIndex === -1) {
|
||||
string = string.slice(0, allowedLength);
|
||||
} else {
|
||||
const filename = string.slice(0, extensionIndex);
|
||||
const extension = string.slice(extensionIndex);
|
||||
string = filename.slice(0, Math.max(1, allowedLength - extension.length)) + extension;
|
||||
}
|
||||
}
|
||||
/* eslint-enable no-param-reassign */
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
module.exports = filenamify;
|
||||
Reference in New Issue
Block a user