Compare 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 | ||
|
|
0ec4b619d9 | ||
|
|
12f05adde7 | ||
|
|
c594e8bd71 | ||
|
|
f84166406f | ||
|
|
82b2ba298d | ||
|
|
38b6805ba1 | ||
|
|
6a7a582045 | ||
|
|
c53a00b4ba | ||
|
|
52103c775b | ||
|
|
eeb1bd80cc | ||
|
|
e6b8538863 | ||
|
|
9dc38932fb | ||
|
|
e9b4a4adfc | ||
|
|
76c78c7252 | ||
|
|
04f52a63f2 | ||
|
|
6b16a104b1 | ||
|
|
aff853c602 | ||
|
|
ad2966c5d6 | ||
|
|
8d74cc1732 | ||
|
|
ea94fe8bf3 | ||
|
|
6052f8999f | ||
|
|
67d1b1c194 | ||
|
|
b3cb8405f5 | ||
|
|
7acaec6d04 |
@@ -1 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
npx lint-staged
|
npx lint-staged
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Planka
|
# Planka
|
||||||
#### Elegant open source project tracking.
|
#### Elegant open source project tracking.
|
||||||
|
|
||||||
  
|
  
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ type: application
|
|||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# 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.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
version: 0.2.2
|
version: 0.2.8
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# 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
|
# 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.
|
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||||
# It is recommended to use it with quotes.
|
# It is recommended to use it with quotes.
|
||||||
appVersion: "1.19.1"
|
appVersion: "1.22.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
- alias: postgresql
|
- alias: postgresql
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ spec:
|
|||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
{{- include "planka.selectorLabels" . | nindent 6 }}
|
{{- include "planka.selectorLabels" . | nindent 6 }}
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
{{- end }}
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
{{- with .Values.podAnnotations }}
|
{{- with .Values.podAnnotations }}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
REACT_APP_VERSION=1.19.1
|
|
||||||
Generated
+2055
-7110
File diff suppressed because it is too large
Load Diff
+12
-11
@@ -65,7 +65,7 @@
|
|||||||
"dequal": "^2.0.3",
|
"dequal": "^2.0.3",
|
||||||
"easymde": "^2.18.0",
|
"easymde": "^2.18.0",
|
||||||
"history": "^5.3.0",
|
"history": "^5.3.0",
|
||||||
"i18next": "^23.11.5",
|
"i18next": "^23.15.1",
|
||||||
"i18next-browser-languagedetector": "^8.0.0",
|
"i18next-browser-languagedetector": "^8.0.0",
|
||||||
"initials": "^3.1.2",
|
"initials": "^3.1.2",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
@@ -77,18 +77,18 @@
|
|||||||
"node-sass": "^9.0.0",
|
"node-sass": "^9.0.0",
|
||||||
"photoswipe": "^5.4.4",
|
"photoswipe": "^5.4.4",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react": "^18.2.0",
|
"react": "18.2.0",
|
||||||
"react-app-rewired": "^2.2.1",
|
"react-app-rewired": "^2.2.1",
|
||||||
"react-beautiful-dnd": "^13.1.1",
|
"react-beautiful-dnd": "^13.1.1",
|
||||||
"react-datepicker": "^4.25.0",
|
"react-datepicker": "^4.25.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-dropzone": "^14.2.3",
|
"react-dropzone": "^14.2.3",
|
||||||
"react-i18next": "^14.1.2",
|
"react-i18next": "^15.0.2",
|
||||||
"react-input-mask": "^2.0.4",
|
"react-input-mask": "^2.0.4",
|
||||||
"react-markdown": "^8.0.7",
|
"react-markdown": "^8.0.7",
|
||||||
"react-photoswipe-gallery": "^2.2.7",
|
"react-photoswipe-gallery": "^2.2.7",
|
||||||
"react-redux": "^8.1.3",
|
"react-redux": "^8.1.3",
|
||||||
"react-router-dom": "^6.23.1",
|
"react-router-dom": "^6.26.2",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"react-simplemde-editor": "^5.2.0",
|
"react-simplemde-editor": "^5.2.0",
|
||||||
"react-textarea-autosize": "^8.5.3",
|
"react-textarea-autosize": "^8.5.3",
|
||||||
@@ -107,17 +107,18 @@
|
|||||||
"zxcvbn": "^4.4.2"
|
"zxcvbn": "^4.4.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"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/react": "^15.0.7",
|
||||||
"@testing-library/user-event": "^14.5.2",
|
"@testing-library/user-event": "^14.5.2",
|
||||||
"babel-preset-airbnb": "^5.0.0",
|
"babel-preset-airbnb": "^5.0.0",
|
||||||
"chai": "^4.4.1",
|
"chai": "^4.5.0",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.30.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
"eslint-plugin-jsx-a11y": "^6.10.0",
|
||||||
"eslint-plugin-react": "^7.34.2",
|
"eslint-plugin-react": "^7.36.1",
|
||||||
"eslint-plugin-react-hooks": "^4.6.2",
|
"eslint-plugin-react-hooks": "^4.6.2",
|
||||||
"react-test-renderer": "^18.2.0"
|
"react-test-renderer": "18.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
|
|||||||
@@ -57,10 +57,15 @@ updateCard.failure = (id, error) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleCardUpdate = (card) => ({
|
const handleCardUpdate = (card, isFetched, cardMemberships, cardLabels, tasks, attachments) => ({
|
||||||
type: ActionTypes.CARD_UPDATE_HANDLE,
|
type: ActionTypes.CARD_UPDATE_HANDLE,
|
||||||
payload: {
|
payload: {
|
||||||
card,
|
card,
|
||||||
|
isFetched,
|
||||||
|
cardMemberships,
|
||||||
|
cardLabels,
|
||||||
|
tasks,
|
||||||
|
attachments,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import http from './http';
|
import http from './http';
|
||||||
import socket from './socket';
|
|
||||||
|
|
||||||
/* Actions */
|
/* 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) =>
|
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) =>
|
const deleteCurrentAccessToken = (headers) => http.delete('/access-tokens/me', undefined, headers);
|
||||||
socket.delete('/access-tokens/me', undefined, headers);
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createAccessToken,
|
createAccessToken,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Config from '../constants/Config';
|
|||||||
const http = {};
|
const http = {};
|
||||||
|
|
||||||
// TODO: add all methods
|
// TODO: add all methods
|
||||||
['GET', 'POST'].forEach((method) => {
|
['GET', 'POST', 'DELETE'].forEach((method) => {
|
||||||
http[method.toLowerCase()] = (url, data, headers) => {
|
http[method.toLowerCase()] = (url, data, headers) => {
|
||||||
const formData =
|
const formData =
|
||||||
data &&
|
data &&
|
||||||
@@ -19,6 +19,7 @@ const http = {};
|
|||||||
method,
|
method,
|
||||||
headers,
|
headers,
|
||||||
body: formData,
|
body: formData,
|
||||||
|
credentials: 'include',
|
||||||
})
|
})
|
||||||
.then((response) =>
|
.then((response) =>
|
||||||
response.json().then((body) => ({
|
response.json().then((body) => ({
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
:global(#app) {
|
:global(#app) {
|
||||||
.wrapper {
|
.wrapper {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
max-height: 100vh;
|
||||||
|
max-width: 100vw;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
|
|||||||
@@ -48,16 +48,6 @@
|
|||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel {
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panelItem {
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
margin: 0 20px;
|
margin: 0 20px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,13 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
margin-right: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
justify-content: flex-start;
|
||||||
margin: 20px 20px;
|
margin: 20px 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,10 @@
|
|||||||
transition: width 0.2s ease;
|
transition: width 0.2s ease;
|
||||||
width: 280px;
|
width: 280px;
|
||||||
|
|
||||||
|
@media only screen and (max-width: 797px) {
|
||||||
|
width: 220px;
|
||||||
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ const Card = React.memo(
|
|||||||
index,
|
index,
|
||||||
name,
|
name,
|
||||||
dueDate,
|
dueDate,
|
||||||
|
isDueDateCompleted,
|
||||||
stopwatch,
|
stopwatch,
|
||||||
coverUrl,
|
coverUrl,
|
||||||
boardId,
|
boardId,
|
||||||
@@ -120,7 +121,7 @@ const Card = React.memo(
|
|||||||
)}
|
)}
|
||||||
{dueDate && (
|
{dueDate && (
|
||||||
<span className={classNames(styles.attachment, styles.attachmentLeft)}>
|
<span className={classNames(styles.attachment, styles.attachmentLeft)}>
|
||||||
<DueDate value={dueDate} size="tiny" />
|
<DueDate value={dueDate} isCompleted={isDueDateCompleted} size="tiny" />
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{stopwatch && (
|
{stopwatch && (
|
||||||
@@ -221,6 +222,7 @@ Card.propTypes = {
|
|||||||
index: PropTypes.number.isRequired,
|
index: PropTypes.number.isRequired,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
dueDate: PropTypes.instanceOf(Date),
|
dueDate: PropTypes.instanceOf(Date),
|
||||||
|
isDueDateCompleted: PropTypes.bool,
|
||||||
stopwatch: PropTypes.object, // eslint-disable-line react/forbid-prop-types
|
stopwatch: PropTypes.object, // eslint-disable-line react/forbid-prop-types
|
||||||
coverUrl: PropTypes.string,
|
coverUrl: PropTypes.string,
|
||||||
boardId: PropTypes.string.isRequired,
|
boardId: PropTypes.string.isRequired,
|
||||||
@@ -255,6 +257,7 @@ Card.propTypes = {
|
|||||||
|
|
||||||
Card.defaultProps = {
|
Card.defaultProps = {
|
||||||
dueDate: undefined,
|
dueDate: undefined,
|
||||||
|
isDueDateCompleted: undefined,
|
||||||
stopwatch: undefined,
|
stopwatch: undefined,
|
||||||
coverUrl: undefined,
|
coverUrl: undefined,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,6 +21,14 @@
|
|||||||
background: #ebeef0;
|
background: #ebeef0;
|
||||||
color: #516b7a;
|
color: #516b7a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 797px) {
|
||||||
|
&:focus,
|
||||||
|
&:active {
|
||||||
|
background: #ebeef0;
|
||||||
|
color: #516b7a;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachment {
|
.attachment {
|
||||||
@@ -55,6 +63,12 @@
|
|||||||
box-shadow: 0 1px 0 #ccc;
|
box-shadow: 0 1px 0 #ccc;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@media only screen and (max-width: 797px) {
|
||||||
|
.target {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #f5f6f7;
|
background: #f5f6f7;
|
||||||
border-bottom-color: rgba(9, 30, 66, 0.25);
|
border-bottom-color: rgba(9, 30, 66, 0.25);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
.dropzone {
|
.dropzone {
|
||||||
background: white;
|
background: white;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 700;
|
font-weight: bold;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
.contentError {
|
.contentError {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 700;
|
font-weight: bold;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
width: 470px;
|
width: 470px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
color: #5e6c84;
|
color: #5e6c84;
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 700;
|
font-weight: bold;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
line-height: 80px;
|
line-height: 80px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
.name {
|
.name {
|
||||||
color: #17394d;
|
color: #17394d;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 700;
|
font-weight: bold;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useCallback, useRef, useState } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button, Grid, Icon, Modal } from 'semantic-ui-react';
|
import { Button, Checkbox, Grid, Icon, Modal } from 'semantic-ui-react';
|
||||||
import { usePopup } from '../../lib/popup';
|
import { usePopup } from '../../lib/popup';
|
||||||
import { Markdown } from '../../lib/custom-ui';
|
import { Markdown } from '../../lib/custom-ui';
|
||||||
|
|
||||||
@@ -32,6 +32,7 @@ const CardModal = React.memo(
|
|||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
dueDate,
|
dueDate,
|
||||||
|
isDueDateCompleted,
|
||||||
stopwatch,
|
stopwatch,
|
||||||
isSubscribed,
|
isSubscribed,
|
||||||
isActivitiesFetching,
|
isActivitiesFetching,
|
||||||
@@ -118,6 +119,12 @@ const CardModal = React.memo(
|
|||||||
[onUpdate],
|
[onUpdate],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleDueDateCompletionChange = useCallback(() => {
|
||||||
|
onUpdate({
|
||||||
|
isDueDateCompleted: !isDueDateCompleted,
|
||||||
|
});
|
||||||
|
}, [isDueDateCompleted, onUpdate]);
|
||||||
|
|
||||||
const handleStopwatchUpdate = useCallback(
|
const handleStopwatchUpdate = useCallback(
|
||||||
(newStopwatch) => {
|
(newStopwatch) => {
|
||||||
onUpdate({
|
onUpdate({
|
||||||
@@ -300,13 +307,24 @@ const CardModal = React.memo(
|
|||||||
context: 'title',
|
context: 'title',
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<span className={styles.attachment}>
|
<span className={classNames(styles.attachment, styles.attachmentDueDate)}>
|
||||||
{canEdit ? (
|
{canEdit ? (
|
||||||
<DueDateEditPopup defaultValue={dueDate} onUpdate={handleDueDateUpdate}>
|
<>
|
||||||
<DueDate value={dueDate} />
|
<Checkbox
|
||||||
</DueDateEditPopup>
|
checked={isDueDateCompleted}
|
||||||
|
disabled={!canEdit}
|
||||||
|
onChange={handleDueDateCompletionChange}
|
||||||
|
/>
|
||||||
|
<DueDateEditPopup defaultValue={dueDate} onUpdate={handleDueDateUpdate}>
|
||||||
|
<DueDate
|
||||||
|
withStatusIcon
|
||||||
|
value={dueDate}
|
||||||
|
isCompleted={isDueDateCompleted}
|
||||||
|
/>
|
||||||
|
</DueDateEditPopup>
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<DueDate value={dueDate} />
|
<DueDate withStatusIcon value={dueDate} isCompleted={isDueDateCompleted} />
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -515,14 +533,19 @@ const CardModal = React.memo(
|
|||||||
<Icon name="copy outline" className={styles.actionIcon} />
|
<Icon name="copy outline" className={styles.actionIcon} />
|
||||||
{t('action.duplicate')}
|
{t('action.duplicate')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button fluid className={styles.actionButton} onClick={handleCopyLinkClick}>
|
{window.isSecureContext && (
|
||||||
<Icon name={isLinkCopied ? 'linkify' : 'unlink'} className={styles.actionIcon} />
|
<Button fluid className={styles.actionButton} onClick={handleCopyLinkClick}>
|
||||||
{isLinkCopied
|
<Icon
|
||||||
? t('common.linkIsCopied')
|
name={isLinkCopied ? 'linkify' : 'unlink'}
|
||||||
: t('action.copyLink', {
|
className={styles.actionIcon}
|
||||||
context: 'title',
|
/>
|
||||||
})}
|
{isLinkCopied
|
||||||
</Button>
|
? t('common.linkIsCopied')
|
||||||
|
: t('action.copyLink', {
|
||||||
|
context: 'title',
|
||||||
|
})}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<DeletePopup
|
<DeletePopup
|
||||||
title="common.deleteCard"
|
title="common.deleteCard"
|
||||||
content="common.areYouSureYouWantToDeleteThisCard"
|
content="common.areYouSureYouWantToDeleteThisCard"
|
||||||
@@ -557,6 +580,7 @@ CardModal.propTypes = {
|
|||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
description: PropTypes.string,
|
description: PropTypes.string,
|
||||||
dueDate: PropTypes.instanceOf(Date),
|
dueDate: PropTypes.instanceOf(Date),
|
||||||
|
isDueDateCompleted: PropTypes.bool,
|
||||||
stopwatch: PropTypes.object, // eslint-disable-line react/forbid-prop-types
|
stopwatch: PropTypes.object, // eslint-disable-line react/forbid-prop-types
|
||||||
isSubscribed: PropTypes.bool.isRequired,
|
isSubscribed: PropTypes.bool.isRequired,
|
||||||
isActivitiesFetching: PropTypes.bool.isRequired,
|
isActivitiesFetching: PropTypes.bool.isRequired,
|
||||||
@@ -611,6 +635,7 @@ CardModal.propTypes = {
|
|||||||
CardModal.defaultProps = {
|
CardModal.defaultProps = {
|
||||||
description: undefined,
|
description: undefined,
|
||||||
dueDate: undefined,
|
dueDate: undefined,
|
||||||
|
isDueDateCompleted: false,
|
||||||
stopwatch: undefined,
|
stopwatch: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -25,12 +25,21 @@
|
|||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
@media only screen and (max-width: 797px) {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 425px) {
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionsTitle {
|
.actionsTitle {
|
||||||
color: #8c8c8c;
|
color: #8c8c8c;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 500;
|
font-weight: normal;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
@@ -49,6 +58,12 @@
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.attachmentDueDate {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.attachments {
|
.attachments {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0 8px 8px 0;
|
margin: 0 8px 8px 0;
|
||||||
@@ -62,6 +77,11 @@
|
|||||||
|
|
||||||
.contentPadding {
|
.contentPadding {
|
||||||
padding: 8px 8px 0 16px;
|
padding: 8px 8px 0 16px;
|
||||||
|
|
||||||
|
@media only screen and (max-width: 797px) {
|
||||||
|
padding-right: 16px;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cursorPointer {
|
.cursorPointer {
|
||||||
@@ -138,7 +158,7 @@
|
|||||||
.headerTitle {
|
.headerTitle {
|
||||||
color: #17394d;
|
color: #17394d;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 700;
|
font-weight: bold;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +174,11 @@
|
|||||||
|
|
||||||
.modalPadding {
|
.modalPadding {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
|
||||||
|
@media only screen and (max-width: 797px) {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.moduleHeader {
|
.moduleHeader {
|
||||||
@@ -184,6 +209,15 @@
|
|||||||
|
|
||||||
.sidebarPadding {
|
.sidebarPadding {
|
||||||
padding: 8px 16px 0 8px;
|
padding: 8px 16px 0 8px;
|
||||||
|
|
||||||
|
@media only screen and (max-width: 797px) {
|
||||||
|
align-items: flex-start;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
gap: 10px;
|
||||||
|
padding-left: 16px;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
color: #17394d;
|
color: #17394d;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 700;
|
font-weight: bold;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
margin: -5px;
|
margin: -5px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
bottom: 20px;
|
bottom: 20px;
|
||||||
box-shadow: #b04632 0 1px 0;
|
box-shadow: #b04632 0 1px 0;
|
||||||
|
max-width: calc(100% - 40px);
|
||||||
padding: 12px 18px;
|
padding: 12px 18px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import upperFirst from 'lodash/upperFirst';
|
import upperFirst from 'lodash/upperFirst';
|
||||||
import React from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Icon } from 'semantic-ui-react';
|
||||||
|
import { useForceUpdate } from '../../lib/hooks';
|
||||||
|
|
||||||
import getDateFormat from '../../utils/get-date-format';
|
import getDateFormat from '../../utils/get-date-format';
|
||||||
|
|
||||||
@@ -14,6 +16,12 @@ const SIZES = {
|
|||||||
MEDIUM: 'medium',
|
MEDIUM: 'medium',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const STATUSES = {
|
||||||
|
DUE_SOON: 'dueSoon',
|
||||||
|
OVERDUE: 'overdue',
|
||||||
|
COMPLETED: 'completed',
|
||||||
|
};
|
||||||
|
|
||||||
const LONG_DATE_FORMAT_BY_SIZE = {
|
const LONG_DATE_FORMAT_BY_SIZE = {
|
||||||
tiny: 'longDate',
|
tiny: 'longDate',
|
||||||
small: 'longDate',
|
small: 'longDate',
|
||||||
@@ -26,8 +34,47 @@ const FULL_DATE_FORMAT_BY_SIZE = {
|
|||||||
medium: 'fullDateTime',
|
medium: 'fullDateTime',
|
||||||
};
|
};
|
||||||
|
|
||||||
const DueDate = React.memo(({ value, size, isDisabled, onClick }) => {
|
const STATUS_ICON_PROPS_BY_STATUS = {
|
||||||
|
[STATUSES.DUE_SOON]: {
|
||||||
|
name: 'hourglass half',
|
||||||
|
color: 'orange',
|
||||||
|
},
|
||||||
|
[STATUSES.OVERDUE]: {
|
||||||
|
name: 'hourglass end',
|
||||||
|
color: 'red',
|
||||||
|
},
|
||||||
|
[STATUSES.COMPLETED]: {
|
||||||
|
name: 'checkmark',
|
||||||
|
color: 'green',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatus = (dateTime, isCompleted) => {
|
||||||
|
if (isCompleted) {
|
||||||
|
return STATUSES.COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
const secondsLeft = Math.floor((dateTime.getTime() - new Date().getTime()) / 1000);
|
||||||
|
|
||||||
|
if (secondsLeft <= 0) {
|
||||||
|
return STATUSES.OVERDUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secondsLeft <= 24 * 60 * 60) {
|
||||||
|
return STATUSES.DUE_SOON;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DueDate = React.memo(({ value, size, isCompleted, isDisabled, withStatusIcon, onClick }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
const forceUpdate = useForceUpdate();
|
||||||
|
|
||||||
|
const statusRef = useRef(null);
|
||||||
|
statusRef.current = getStatus(value, isCompleted);
|
||||||
|
|
||||||
|
const intervalRef = useRef(null);
|
||||||
|
|
||||||
const dateFormat = getDateFormat(
|
const dateFormat = getDateFormat(
|
||||||
value,
|
value,
|
||||||
@@ -35,11 +82,34 @@ const DueDate = React.memo(({ value, size, isDisabled, onClick }) => {
|
|||||||
FULL_DATE_FORMAT_BY_SIZE[size],
|
FULL_DATE_FORMAT_BY_SIZE[size],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if ([null, STATUSES.DUE_SOON].includes(statusRef.current)) {
|
||||||
|
intervalRef.current = setInterval(() => {
|
||||||
|
const status = getStatus(value, isCompleted);
|
||||||
|
|
||||||
|
if (status !== statusRef.current) {
|
||||||
|
forceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status === STATUSES.OVERDUE) {
|
||||||
|
clearInterval(intervalRef.current);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (intervalRef.current) {
|
||||||
|
clearInterval(intervalRef.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [value, isCompleted, forceUpdate]);
|
||||||
|
|
||||||
const contentNode = (
|
const contentNode = (
|
||||||
<span
|
<span
|
||||||
className={classNames(
|
className={classNames(
|
||||||
styles.wrapper,
|
styles.wrapper,
|
||||||
styles[`wrapper${upperFirst(size)}`],
|
styles[`wrapper${upperFirst(size)}`],
|
||||||
|
!withStatusIcon && statusRef.current && styles[`wrapper${upperFirst(statusRef.current)}`],
|
||||||
onClick && styles.wrapperHoverable,
|
onClick && styles.wrapperHoverable,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -47,6 +117,10 @@ const DueDate = React.memo(({ value, size, isDisabled, onClick }) => {
|
|||||||
value,
|
value,
|
||||||
postProcess: 'formatDate',
|
postProcess: 'formatDate',
|
||||||
})}
|
})}
|
||||||
|
{withStatusIcon && statusRef.current && (
|
||||||
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
|
<Icon {...STATUS_ICON_PROPS_BY_STATUS[statusRef.current]} className={styles.statusIcon} />
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -62,14 +136,19 @@ const DueDate = React.memo(({ value, size, isDisabled, onClick }) => {
|
|||||||
DueDate.propTypes = {
|
DueDate.propTypes = {
|
||||||
value: PropTypes.instanceOf(Date).isRequired,
|
value: PropTypes.instanceOf(Date).isRequired,
|
||||||
size: PropTypes.oneOf(Object.values(SIZES)),
|
size: PropTypes.oneOf(Object.values(SIZES)),
|
||||||
|
isCompleted: PropTypes.bool.isRequired,
|
||||||
isDisabled: PropTypes.bool,
|
isDisabled: PropTypes.bool,
|
||||||
|
withStatusIcon: PropTypes.bool,
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
|
onCompletionToggle: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
DueDate.defaultProps = {
|
DueDate.defaultProps = {
|
||||||
size: SIZES.MEDIUM,
|
size: SIZES.MEDIUM,
|
||||||
isDisabled: false,
|
isDisabled: false,
|
||||||
|
withStatusIcon: false,
|
||||||
onClick: undefined,
|
onClick: undefined,
|
||||||
|
onCompletionToggle: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DueDate;
|
export default DueDate;
|
||||||
|
|||||||
@@ -8,16 +8,17 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.statusIcon {
|
||||||
|
line-height: 1;
|
||||||
|
margin: 0 0 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
background: #dce0e4;
|
background: #dce0e4;
|
||||||
border: none;
|
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
color: #6a808b;
|
color: #6a808b;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
outline: none;
|
|
||||||
text-align: left;
|
|
||||||
transition: background 0.3s ease;
|
transition: background 0.3s ease;
|
||||||
vertical-align: top;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapperHoverable:hover {
|
.wrapperHoverable:hover {
|
||||||
@@ -43,4 +44,21 @@
|
|||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Statuses */
|
||||||
|
|
||||||
|
.wrapperDueSoon {
|
||||||
|
background: #f2711c;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapperOverdue {
|
||||||
|
background: #db2828;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapperCompleted {
|
||||||
|
background: #21ba45;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
:global(#app) {
|
:global(#app) {
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
max-width: 100vw;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|||||||
@@ -87,7 +87,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.userName {
|
.userName {
|
||||||
|
display: none;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
|
||||||
|
@media only screen and (min-width: 797px) {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const SIZES = {
|
|||||||
|
|
||||||
const Label = React.memo(({ name, color, size, isDisabled, onClick }) => {
|
const Label = React.memo(({ name, color, size, isDisabled, onClick }) => {
|
||||||
const contentNode = (
|
const contentNode = (
|
||||||
<div
|
<span
|
||||||
title={name}
|
title={name}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
styles.wrapper,
|
styles.wrapper,
|
||||||
@@ -28,7 +28,7 @@ const Label = React.memo(({ name, color, size, isDisabled, onClick }) => {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{name || '\u00A0'}
|
{name || '\u00A0'}
|
||||||
</div>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
return onClick ? (
|
return onClick ? (
|
||||||
|
|||||||
@@ -11,17 +11,17 @@
|
|||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
box-sizing: border-box;
|
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-weight: 400;
|
display: inline-block;
|
||||||
outline: none;
|
font-weight: normal;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
|
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
vertical-align: top;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapperNameless{
|
.wrapperNameless {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,12 @@
|
|||||||
&:hover .target {
|
&:hover .target {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 797px) {
|
||||||
|
.target {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.headerEditable {
|
.headerEditable {
|
||||||
@@ -103,6 +109,15 @@
|
|||||||
background: rgba(9, 30, 66, 0.13);
|
background: rgba(9, 30, 66, 0.13);
|
||||||
color: #516b7a;
|
color: #516b7a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 797px) {
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&:active {
|
||||||
|
background: rgba(9, 30, 66, 0.13);
|
||||||
|
color: #516b7a;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.headerName {
|
.headerName {
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ const createMessage = (error) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (error.message) {
|
switch (error.message) {
|
||||||
|
case 'Invalid credentials':
|
||||||
|
return {
|
||||||
|
type: 'error',
|
||||||
|
content: 'common.invalidCredentials',
|
||||||
|
};
|
||||||
case 'Invalid email or username':
|
case 'Invalid email or username':
|
||||||
return {
|
return {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
@@ -116,6 +121,7 @@ const Login = React.memo(
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (wasSubmitting && !isSubmitting && error) {
|
if (wasSubmitting && !isSubmitting && error) {
|
||||||
switch (error.message) {
|
switch (error.message) {
|
||||||
|
case 'Invalid credentials':
|
||||||
case 'Invalid email or username':
|
case 'Invalid email or username':
|
||||||
emailOrUsernameField.current.select();
|
emailOrUsernameField.current.select();
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,10 @@
|
|||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
width: 36px;
|
width: 36px;
|
||||||
|
|
||||||
|
@media only screen and (max-width: 797px) {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(0, 0, 0, 0.32);
|
background: rgba(0, 0, 0, 0.32);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,10 @@
|
|||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
background: #dce0e4;
|
background: #dce0e4;
|
||||||
border: none;
|
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
color: #6a808b;
|
color: #6a808b;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
outline: none;
|
|
||||||
text-align: left;
|
|
||||||
transition: background 0.3s ease;
|
transition: background 0.3s ease;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,12 +14,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
border: none;
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
outline: none;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
@@ -32,7 +30,6 @@
|
|||||||
|
|
||||||
.wrapperTiny {
|
.wrapperTiny {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
font-weight: 400;
|
|
||||||
height: 24px;
|
height: 24px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
padding: 2px 0;
|
padding: 2px 0;
|
||||||
@@ -41,7 +38,6 @@
|
|||||||
|
|
||||||
.wrapperSmall {
|
.wrapperSmall {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 400;
|
|
||||||
height: 28px;
|
height: 28px;
|
||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
width: 28px;
|
width: 28px;
|
||||||
@@ -49,7 +45,6 @@
|
|||||||
|
|
||||||
.wrapperMedium {
|
.wrapperMedium {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
|
||||||
height: 32px;
|
height: 32px;
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
@@ -57,7 +52,6 @@
|
|||||||
|
|
||||||
.wrapperLarge {
|
.wrapperLarge {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
|
||||||
height: 36px;
|
height: 36px;
|
||||||
padding: 12px 0 10px;
|
padding: 12px 0 10px;
|
||||||
width: 36px;
|
width: 36px;
|
||||||
@@ -65,7 +59,6 @@
|
|||||||
|
|
||||||
.wrapperMassive {
|
.wrapperMassive {
|
||||||
font-size: 36px;
|
font-size: 36px;
|
||||||
font-weight: 500;
|
|
||||||
height: 100px;
|
height: 100px;
|
||||||
padding: 32px 0 10px;
|
padding: 32px 0 10px;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Image, Tab } from 'semantic-ui-react';
|
import { Image, Tab } from 'semantic-ui-react';
|
||||||
|
|
||||||
import Config from '../../constants/Config';
|
import version from '../../version';
|
||||||
|
|
||||||
import logo from '../../assets/images/logo.png';
|
import logo from '../../assets/images/logo.png';
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ const AboutPane = React.memo(() => {
|
|||||||
<Tab.Pane attached={false} className={styles.wrapper}>
|
<Tab.Pane attached={false} className={styles.wrapper}>
|
||||||
<Image centered src={logo} size="large" />
|
<Image centered src={logo} size="large" />
|
||||||
<div className={styles.version}>
|
<div className={styles.version}>
|
||||||
{t('common.version')} {Config.VERSION}
|
{t('common.version')} {version}
|
||||||
</div>
|
</div>
|
||||||
</Tab.Pane>
|
</Tab.Pane>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -195,9 +195,6 @@ export default {
|
|||||||
CARD_UPDATE__SUCCESS: 'CARD_UPDATE__SUCCESS',
|
CARD_UPDATE__SUCCESS: 'CARD_UPDATE__SUCCESS',
|
||||||
CARD_UPDATE__FAILURE: 'CARD_UPDATE__FAILURE',
|
CARD_UPDATE__FAILURE: 'CARD_UPDATE__FAILURE',
|
||||||
CARD_UPDATE_HANDLE: 'CARD_UPDATE_HANDLE',
|
CARD_UPDATE_HANDLE: 'CARD_UPDATE_HANDLE',
|
||||||
CARD_TRANSFER: 'CARD_TRANSFER',
|
|
||||||
CARD_TRANSFER__SUCCESS: 'CARD_TRANSFER__SUCCESS',
|
|
||||||
CARD_TRANSFER__FAILURE: 'CARD_TRANSFER__FAILURE',
|
|
||||||
CARD_DUPLICATE: 'CARD_DUPLICATE',
|
CARD_DUPLICATE: 'CARD_DUPLICATE',
|
||||||
CARD_DUPLICATE__SUCCESS: 'CARD_DUPLICATE__SUCCESS',
|
CARD_DUPLICATE__SUCCESS: 'CARD_DUPLICATE__SUCCESS',
|
||||||
CARD_DUPLICATE__FAILURE: 'CARD_DUPLICATE__FAILURE',
|
CARD_DUPLICATE__FAILURE: 'CARD_DUPLICATE__FAILURE',
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
const VERSION = process.env.REACT_APP_VERSION;
|
|
||||||
|
|
||||||
const { BASE_URL } = window;
|
const { BASE_URL } = window;
|
||||||
|
|
||||||
const BASE_PATH = BASE_URL.replace(/^.*\/\/[^/]*(.*)[^?#]*.*$/, '$1');
|
const BASE_PATH = BASE_URL.replace(/^.*\/\/[^/]*(.*)[^?#]*.*$/, '$1');
|
||||||
|
|
||||||
const SERVER_BASE_URL =
|
const SERVER_BASE_URL =
|
||||||
process.env.REACT_APP_SERVER_BASE_URL ||
|
process.env.REACT_APP_SERVER_BASE_URL ||
|
||||||
(process.env.NODE_ENV === 'production' ? BASE_URL : 'http://localhost:1337');
|
(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 SERVER_HOST_NAME = SERVER_BASE_URL.replace(/^(.*\/\/[^/?#]*).*$/, '$1');
|
||||||
|
|
||||||
const ACCESS_TOKEN_KEY = 'accessToken';
|
const ACCESS_TOKEN_KEY = 'accessToken';
|
||||||
@@ -18,7 +17,6 @@ const POSITION_GAP = 65535;
|
|||||||
const ACTIVITIES_LIMIT = 50;
|
const ACTIVITIES_LIMIT = 50;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
VERSION,
|
|
||||||
BASE_PATH,
|
BASE_PATH,
|
||||||
SERVER_BASE_URL,
|
SERVER_BASE_URL,
|
||||||
SERVER_BASE_PATH,
|
SERVER_BASE_PATH,
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ const makeMapStateToProps = () => {
|
|||||||
const allLabels = selectors.selectLabelsForCurrentBoard(state);
|
const allLabels = selectors.selectLabelsForCurrentBoard(state);
|
||||||
const currentUserMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
|
const currentUserMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
|
||||||
|
|
||||||
const { name, dueDate, stopwatch, coverUrl, boardId, listId, isPersisted } = selectCardById(
|
const { name, dueDate, isDueDateCompleted, stopwatch, coverUrl, boardId, listId, isPersisted } =
|
||||||
state,
|
selectCardById(state, id);
|
||||||
id,
|
|
||||||
);
|
|
||||||
|
|
||||||
const users = selectUsersByCardId(state, id);
|
const users = selectUsersByCardId(state, id);
|
||||||
const labels = selectLabelsByCardId(state, id);
|
const labels = selectLabelsByCardId(state, id);
|
||||||
@@ -38,6 +36,7 @@ const makeMapStateToProps = () => {
|
|||||||
index,
|
index,
|
||||||
name,
|
name,
|
||||||
dueDate,
|
dueDate,
|
||||||
|
isDueDateCompleted,
|
||||||
stopwatch,
|
stopwatch,
|
||||||
coverUrl,
|
coverUrl,
|
||||||
boardId,
|
boardId,
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ const mapStateToProps = (state) => {
|
|||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
dueDate,
|
dueDate,
|
||||||
|
isDueDateCompleted,
|
||||||
stopwatch,
|
stopwatch,
|
||||||
isSubscribed,
|
isSubscribed,
|
||||||
isActivitiesFetching,
|
isActivitiesFetching,
|
||||||
@@ -49,6 +50,7 @@ const mapStateToProps = (state) => {
|
|||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
dueDate,
|
dueDate,
|
||||||
|
isDueDateCompleted,
|
||||||
stopwatch,
|
stopwatch,
|
||||||
isSubscribed,
|
isSubscribed,
|
||||||
isActivitiesFetching,
|
isActivitiesFetching,
|
||||||
|
|||||||
+3
-3
@@ -58,9 +58,9 @@ i18n
|
|||||||
.use(initReactI18next)
|
.use(initReactI18next)
|
||||||
.init({
|
.init({
|
||||||
resources: embeddedLocales,
|
resources: embeddedLocales,
|
||||||
fallbackLng: 'en',
|
fallbackLng: 'en-US',
|
||||||
supportedLngs: languages,
|
supportedLngs: languages,
|
||||||
load: 'languageOnly',
|
load: 'currentOnly',
|
||||||
interpolation: {
|
interpolation: {
|
||||||
escapeValue: false,
|
escapeValue: false,
|
||||||
format(value, format, language) {
|
format(value, format, language) {
|
||||||
@@ -80,7 +80,7 @@ i18n
|
|||||||
});
|
});
|
||||||
|
|
||||||
i18n.loadCoreLocale = async (language = i18n.resolvedLanguage) => {
|
i18n.loadCoreLocale = async (language = i18n.resolvedLanguage) => {
|
||||||
if (language === 'en') {
|
if (language === i18n.options.fallbackLng[0]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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 b,
|
||||||
.markdown-body strong {
|
.markdown-body strong {
|
||||||
font-weight: 600;
|
font-weight: bold; // 600
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body dfn {
|
.markdown-body dfn {
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
|
|
||||||
.markdown-body h1 {
|
.markdown-body h1 {
|
||||||
margin: .67em 0;
|
margin: .67em 0;
|
||||||
font-weight: 600;
|
font-weight: bold; // 600
|
||||||
padding-bottom: .3em;
|
padding-bottom: .3em;
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
border-bottom: 1px solid hsla(210, 18%, 87%, 1);
|
border-bottom: 1px solid hsla(210, 18%, 87%, 1);
|
||||||
@@ -253,34 +253,34 @@
|
|||||||
.markdown-body h6 {
|
.markdown-body h6 {
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
font-weight: 600;
|
font-weight: bold; // 600
|
||||||
line-height: 1.25;
|
line-height: 1.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body h2 {
|
.markdown-body h2 {
|
||||||
font-weight: 600;
|
font-weight: bold; // 600
|
||||||
padding-bottom: .3em;
|
padding-bottom: .3em;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
border-bottom: 1px solid hsla(210, 18%, 87%, 1);
|
border-bottom: 1px solid hsla(210, 18%, 87%, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body h3 {
|
.markdown-body h3 {
|
||||||
font-weight: 600;
|
font-weight: bold; // 600
|
||||||
font-size: 1.25em;
|
font-size: 1.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body h4 {
|
.markdown-body h4 {
|
||||||
font-weight: 600;
|
font-weight: bold; // 600
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body h5 {
|
.markdown-body h5 {
|
||||||
font-weight: 600;
|
font-weight: bold; // 600
|
||||||
font-size: .875em;
|
font-size: .875em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body h6 {
|
.markdown-body h6 {
|
||||||
font-weight: 600;
|
font-weight: bold; // 600
|
||||||
font-size: .85em;
|
font-size: .85em;
|
||||||
color: #57606a;
|
color: #57606a;
|
||||||
}
|
}
|
||||||
@@ -481,7 +481,7 @@
|
|||||||
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
font-style: normal !important;
|
font-style: normal !important;
|
||||||
font-weight: 400;
|
font-weight: normal; // 400
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
vertical-align: -0.075em;
|
vertical-align: -0.075em;
|
||||||
}
|
}
|
||||||
@@ -650,7 +650,7 @@
|
|||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: 600;
|
font-weight: bold; // 600
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body dl dd {
|
.markdown-body dl dd {
|
||||||
@@ -659,7 +659,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body table th {
|
.markdown-body table th {
|
||||||
font-weight: 600;
|
font-weight: bold; // 600
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body table th,
|
.markdown-body table th,
|
||||||
@@ -868,7 +868,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body .csv-data th {
|
.markdown-body .csv-data th {
|
||||||
font-weight: 600;
|
font-weight: bold; // 600
|
||||||
background: #f6f8fa;
|
background: #f6f8fa;
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
}
|
}
|
||||||
@@ -912,7 +912,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body .task-list-item label {
|
.markdown-body .task-list-item label {
|
||||||
font-weight: 400;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body .task-list-item.enabled label {
|
.markdown-body .task-list-item.enabled label {
|
||||||
|
|||||||
Vendored
+2568
-2729
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
|||||||
import login from './login';
|
import login from './login';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
language: 'bg',
|
language: 'bg-BG',
|
||||||
country: 'bg',
|
country: 'bg',
|
||||||
name: 'Български',
|
name: 'Български',
|
||||||
embeddedLocale: login,
|
embeddedLocale: login,
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import login from './login';
|
import login from './login';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
language: 'cs',
|
language: 'cs-CZ',
|
||||||
country: 'cz',
|
country: 'cz',
|
||||||
name: 'Čeština',
|
name: 'Čeština',
|
||||||
embeddedLocale: login,
|
embeddedLocale: login,
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import login from './login';
|
import login from './login';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
language: 'da',
|
language: 'da-DK',
|
||||||
country: 'dk',
|
country: 'dk',
|
||||||
name: 'Dansk',
|
name: 'Dansk',
|
||||||
embeddedLocale: login,
|
embeddedLocale: login,
|
||||||
@@ -192,6 +192,8 @@ export default {
|
|||||||
deleteTask: 'Aufgabe löschen',
|
deleteTask: 'Aufgabe löschen',
|
||||||
deleteTask_title: 'Aufgabe löschen',
|
deleteTask_title: 'Aufgabe löschen',
|
||||||
deleteUser: 'Benutzer löschen',
|
deleteUser: 'Benutzer löschen',
|
||||||
|
duplicate: 'Kopieren',
|
||||||
|
duplicateCard_title: 'Karte kopieren',
|
||||||
edit: 'Bearbeiten',
|
edit: 'Bearbeiten',
|
||||||
editDueDate_title: 'Fälligkeitsdatum bearbeiten',
|
editDueDate_title: 'Fälligkeitsdatum bearbeiten',
|
||||||
editDescription_title: 'Beschreibung ändern',
|
editDescription_title: 'Beschreibung ändern',
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import login from './login';
|
import login from './login';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
language: 'de',
|
language: 'de-DE',
|
||||||
country: 'de',
|
country: 'de',
|
||||||
name: 'Deutsch',
|
name: 'Deutsch',
|
||||||
embeddedLocale: login,
|
embeddedLocale: login,
|
||||||
@@ -4,8 +4,8 @@ import login from './login';
|
|||||||
import core from './core';
|
import core from './core';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
language: 'en',
|
language: 'en-US',
|
||||||
country: 'gb',
|
country: 'us',
|
||||||
name: 'English',
|
name: 'English',
|
||||||
embeddedLocale: merge(login, core),
|
embeddedLocale: merge(login, core),
|
||||||
};
|
};
|
||||||
@@ -3,6 +3,7 @@ export default {
|
|||||||
common: {
|
common: {
|
||||||
emailOrUsername: 'E-mail or username',
|
emailOrUsername: 'E-mail or username',
|
||||||
invalidEmailOrUsername: 'Invalid e-mail or username',
|
invalidEmailOrUsername: 'Invalid e-mail or username',
|
||||||
|
invalidCredentials: 'Invalid credentials',
|
||||||
invalidPassword: 'Invalid password',
|
invalidPassword: 'Invalid password',
|
||||||
logInToPlanka: 'Log in to Planka',
|
logInToPlanka: 'Log in to Planka',
|
||||||
noInternetConnection: 'No internet connection',
|
noInternetConnection: 'No internet connection',
|
||||||
@@ -43,7 +43,7 @@ export default {
|
|||||||
boardNotFound_title: 'Tablero no encontrado',
|
boardNotFound_title: 'Tablero no encontrado',
|
||||||
cardActions_title: 'Acciones de las tarjetas',
|
cardActions_title: 'Acciones de las tarjetas',
|
||||||
cardNotFound_title: 'tarjeta no encontrada',
|
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',
|
color: 'Color',
|
||||||
createBoard_title: 'Crear Tablero',
|
createBoard_title: 'Crear Tablero',
|
||||||
createLabel_title: 'Crear Etiqueta',
|
createLabel_title: 'Crear Etiqueta',
|
||||||
@@ -53,7 +53,7 @@ export default {
|
|||||||
currentPassword: 'Contraseña Actual',
|
currentPassword: 'Contraseña Actual',
|
||||||
date: 'Fecha',
|
date: 'Fecha',
|
||||||
dueDate_title: 'Fecha de Vencimiento',
|
dueDate_title: 'Fecha de Vencimiento',
|
||||||
deleteAttachment_title: 'Eliminar Adjunto',
|
deleteAttachment_title: 'Borrar Adjunto',
|
||||||
deleteBoard_title: 'Borrar Tablero',
|
deleteBoard_title: 'Borrar Tablero',
|
||||||
deleteCard_title: 'Borrar tarjeta',
|
deleteCard_title: 'Borrar tarjeta',
|
||||||
deleteComment_title: 'Borrar Comentario',
|
deleteComment_title: 'Borrar Comentario',
|
||||||
@@ -72,7 +72,7 @@ export default {
|
|||||||
editLabel_title: 'Editar Etiqueta',
|
editLabel_title: 'Editar Etiqueta',
|
||||||
editPassword_title: 'Editar Contraseña',
|
editPassword_title: 'Editar Contraseña',
|
||||||
editStopwatch_title: 'Editar Temporizador',
|
editStopwatch_title: 'Editar Temporizador',
|
||||||
editUsername_title: 'Edit nombre de usuario',
|
editUsername_title: 'Editar nombre de usuario',
|
||||||
email: 'Correo',
|
email: 'Correo',
|
||||||
emailAlreadyInUse: 'El correo ya está en uso',
|
emailAlreadyInUse: 'El correo ya está en uso',
|
||||||
enterCardTitle: 'Escribe el título de la tarjeta...',
|
enterCardTitle: 'Escribe el título de la tarjeta...',
|
||||||
@@ -85,8 +85,8 @@ export default {
|
|||||||
filterByMembers_title: 'Filtrar por Miembros',
|
filterByMembers_title: 'Filtrar por Miembros',
|
||||||
fromComputer_title: 'Desde Computador',
|
fromComputer_title: 'Desde Computador',
|
||||||
hours: 'Horas',
|
hours: 'Horas',
|
||||||
invalidCurrentPassword: 'Contraseña actual invalida',
|
invalidCurrentPassword: 'Contraseña actual inválida',
|
||||||
labels: 'Etíquetas',
|
labels: 'Etiquetas',
|
||||||
list: 'Lista',
|
list: 'Lista',
|
||||||
listActions_title: 'Acciónes de Lista',
|
listActions_title: 'Acciónes de Lista',
|
||||||
members: 'Miembros',
|
members: 'Miembros',
|
||||||
@@ -168,14 +168,14 @@ export default {
|
|||||||
deleteProject_title: 'Borrar Proyecto',
|
deleteProject_title: 'Borrar Proyecto',
|
||||||
deleteTask: 'Borrar tarea',
|
deleteTask: 'Borrar tarea',
|
||||||
deleteTask_title: 'Borrar Tarea',
|
deleteTask_title: 'Borrar Tarea',
|
||||||
deleteUser: 'Delete usuario',
|
deleteUser: 'Borrar usuario',
|
||||||
edit: 'Editar',
|
edit: 'Editar',
|
||||||
editDueDate_title: 'Editar Fecha de Vencimiento',
|
editDueDate_title: 'Editar Fecha de Vencimiento',
|
||||||
editDescription_title: 'Editar Descripción',
|
editDescription_title: 'Editar Descripción',
|
||||||
editEmail_title: 'Editar Correo',
|
editEmail_title: 'Editar Correo',
|
||||||
editPassword_title: 'Editar Contraseña',
|
editPassword_title: 'Editar Contraseña',
|
||||||
editStopwatch_title: 'Edit Temporizador',
|
editStopwatch_title: 'Editar Temporizador',
|
||||||
editTitle_title: 'Edit Título',
|
editTitle_title: 'Editar Título',
|
||||||
editUsername_title: 'Editar Nombre de Usuario',
|
editUsername_title: 'Editar Nombre de Usuario',
|
||||||
logOut_title: 'Cerrar Sesión',
|
logOut_title: 'Cerrar Sesión',
|
||||||
makeCover_title: 'Hacer Cubierta',
|
makeCover_title: 'Hacer Cubierta',
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import login from './login';
|
import login from './login';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
language: 'es',
|
language: 'es-ES',
|
||||||
country: 'es',
|
country: 'es',
|
||||||
name: 'Español',
|
name: 'Español',
|
||||||
embeddedLocale: login,
|
embeddedLocale: login,
|
||||||
@@ -0,0 +1,254 @@
|
|||||||
|
import dateFns from 'date-fns/locale/fa-IR';
|
||||||
|
|
||||||
|
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:
|
||||||
|
'تمام تغییرات به صورت خودکار ذخیره میشوند<br />بعد از بازیابی ارتباط.',
|
||||||
|
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: 'رنگ',
|
||||||
|
copy_inline: 'کپی',
|
||||||
|
createBoard_title: 'ایجاد برد',
|
||||||
|
createLabel_title: 'ایجاد برچسب',
|
||||||
|
createNewOneOrSelectExistingOne: 'یک جدید ایجاد کنید یا<br />یکی موجود را انتخاب کنید.',
|
||||||
|
createProject_title: 'ایجاد پروژه',
|
||||||
|
createTextFile_title: 'ایجاد فایل متنی',
|
||||||
|
currentPassword: 'رمز عبور فعلی',
|
||||||
|
dangerZone_title: 'منطقه خطر',
|
||||||
|
date: 'تاریخ',
|
||||||
|
dueDate: 'تاریخ سررسید',
|
||||||
|
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: 'عنوان کارت را وارد کنید... [Ctrl+Enter] برای باز شدن خودکار.',
|
||||||
|
enterDescription: 'توضیحات را وارد کنید...',
|
||||||
|
enterFilename: 'نام فایل را وارد کنید',
|
||||||
|
enterListTitle: 'عنوان لیست را وارد کنید...',
|
||||||
|
enterProjectTitle: 'عنوان پروژه را وارد کنید',
|
||||||
|
enterTaskDescription: 'توضیحات وظیفه را وارد کنید...',
|
||||||
|
filterByLabels_title: 'فیلتر بر اساس برچسبها',
|
||||||
|
filterByMembers_title: 'فیلتر بر اساس اعضا',
|
||||||
|
fromComputer_title: 'از کامپیوتر',
|
||||||
|
fromTrello: 'از Trello',
|
||||||
|
general: 'عمومی',
|
||||||
|
hours: 'ساعتها',
|
||||||
|
importBoard_title: 'وارد کردن برد',
|
||||||
|
invalidCurrentPassword: 'رمز عبور فعلی نامعتبر است',
|
||||||
|
labels: 'برچسبها',
|
||||||
|
language: 'زبان',
|
||||||
|
leaveBoard_title: 'ترک برد',
|
||||||
|
leaveProject_title: 'ترک پروژه',
|
||||||
|
linkIsCopied: 'لینک کپی شد',
|
||||||
|
list: 'لیست',
|
||||||
|
listActions_title: 'اقدامات لیست',
|
||||||
|
managers: 'مدیران',
|
||||||
|
managerActions_title: 'اقدامات مدیر',
|
||||||
|
members: 'اعضا',
|
||||||
|
memberActions_title: 'اقدامات عضو',
|
||||||
|
minutes: 'دقیقهها',
|
||||||
|
moveCard_title: 'انتقال کارت',
|
||||||
|
name: 'نام',
|
||||||
|
newestFirst: 'جدیدترین اول',
|
||||||
|
newEmail: 'ایمیل جدید',
|
||||||
|
newPassword: 'رمز عبور جدید',
|
||||||
|
newUsername: 'نام کاربری جدید',
|
||||||
|
noConnectionToServer: 'ارتباط با سرور قطع است',
|
||||||
|
noBoards: 'بردی وجود ندارد',
|
||||||
|
noLists: 'لیستی وجود ندارد',
|
||||||
|
noProjects: 'پروژهای وجود ندارد',
|
||||||
|
notifications: 'اعلانها',
|
||||||
|
noUnreadNotifications: 'اعلان خوانده نشدهای وجود ندارد.',
|
||||||
|
oldestFirst: 'قدیمیترین اول',
|
||||||
|
openBoard_title: 'باز کردن برد',
|
||||||
|
optional_inline: 'اختیاری',
|
||||||
|
organization: 'سازمان',
|
||||||
|
phone: 'تلفن',
|
||||||
|
preferences: 'ترجیحات',
|
||||||
|
pressPasteShortcutToAddAttachmentFromClipboard:
|
||||||
|
'نکته: با فشردن Ctrl-V (Cmd-V در مک) میتوانید پیوست را از کلیپ بورد اضافه کنید.',
|
||||||
|
project: 'پروژه',
|
||||||
|
projectNotFound_title: 'پروژه یافت نشد',
|
||||||
|
removeManager_title: 'حذف مدیر',
|
||||||
|
removeMember_title: 'حذف عضو',
|
||||||
|
searchLabels: 'جستجوی برچسبها...',
|
||||||
|
searchMembers: 'جستجوی اعضا...',
|
||||||
|
searchUsers: 'جستجوی کاربران...',
|
||||||
|
searchCards: 'جستجوی کارتها...',
|
||||||
|
seconds: 'ثانیهها',
|
||||||
|
selectBoard: 'انتخاب برد',
|
||||||
|
selectList: 'انتخاب لیست',
|
||||||
|
selectPermissions_title: 'انتخاب دسترسیها',
|
||||||
|
selectProject: 'انتخاب پروژه',
|
||||||
|
settings: 'تنظیمات',
|
||||||
|
sortList_title: 'مرتبسازی لیست',
|
||||||
|
stopwatch: 'کرنومتر',
|
||||||
|
subscribeToMyOwnCardsByDefault: 'به طور پیشفرض به کارتهای خودم مشترک شوم',
|
||||||
|
taskActions_title: 'اقدامات وظیفه',
|
||||||
|
tasks: 'وظایف',
|
||||||
|
thereIsNoPreviewAvailableForThisAttachment: 'پیش نمایشی برای این پیوست موجود نیست.',
|
||||||
|
time: 'زمان',
|
||||||
|
title: 'عنوان',
|
||||||
|
userActions_title: 'اقدامات کاربر',
|
||||||
|
userAddedThisCardToList: '<0>{{user}}</0><1> این کارت را به {{list}} اضافه کرد</1>',
|
||||||
|
userLeftNewCommentToCard: '{{user}} نظر جدید «{{comment}}» را به <2>{{card}}</2> اضافه کرد',
|
||||||
|
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: 'اضافه کردن کاربر',
|
||||||
|
copyLink_title: 'کپی لینک',
|
||||||
|
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: 'حذف کاربر',
|
||||||
|
duplicate: 'تکرار',
|
||||||
|
duplicateCard_title: 'تکرار کارت',
|
||||||
|
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: 'نمایش کمتر پیوستها',
|
||||||
|
sortList_title: 'مرتبسازی لیست',
|
||||||
|
start: 'شروع',
|
||||||
|
stop: 'توقف',
|
||||||
|
subscribe: 'مشترک شدن',
|
||||||
|
unsubscribe: 'لغو اشتراک',
|
||||||
|
uploadNewAvatar: 'آپلود آواتار جدید',
|
||||||
|
uploadNewImage: 'آپلود تصویر جدید',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import login from './login';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
language: 'fa-IR',
|
||||||
|
country: 'ir',
|
||||||
|
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',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user