API & Client - max sizes and max number of files must be greater than 0 - #71
This commit is contained in:
@@ -196,11 +196,11 @@
|
||||
</dd>
|
||||
<dt class="field-even">Request JSON Object</dt>
|
||||
<dd class="field-even"><ul class="simple">
|
||||
<li><p><strong>gpx_limit_import</strong> (<em>integrer</em>) – max number of files in zip archive</p></li>
|
||||
<li><p><strong>gpx_limit_import</strong> (<em>integer</em>) – max number of files in zip archive</p></li>
|
||||
<li><p><strong>is_registration_enabled</strong> (<em>boolean</em>) – is registration enabled ?</p></li>
|
||||
<li><p><strong>max_single_file_size</strong> (<em>integrer</em>) – max size of a single file</p></li>
|
||||
<li><p><strong>max_zip_file_size</strong> (<em>integrer</em>) – max size of a zip archive</p></li>
|
||||
<li><p><strong>max_users</strong> (<em>integrer</em>) – max users allowed to register on instance</p></li>
|
||||
<li><p><strong>max_single_file_size</strong> (<em>integer</em>) – max size of a single file</p></li>
|
||||
<li><p><strong>max_zip_file_size</strong> (<em>integer</em>) – max size of a zip archive</p></li>
|
||||
<li><p><strong>max_users</strong> (<em>integer</em>) – max users allowed to register on instance</p></li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt class="field-odd">Request Headers</dt>
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -12,7 +12,7 @@ from fittrackee.responses import (
|
||||
from fittrackee.users.decorators import authenticate_as_admin
|
||||
|
||||
from .models import AppConfig
|
||||
from .utils import update_app_config_from_database
|
||||
from .utils import update_app_config_from_database, verify_app_config
|
||||
|
||||
config_blueprint = Blueprint('config', __name__)
|
||||
|
||||
@@ -96,11 +96,11 @@ def update_application_config(auth_user_id: int) -> Union[Dict, HttpResponse]:
|
||||
|
||||
:param integer auth_user_id: authenticate user id (from JSON Web Token)
|
||||
|
||||
:<json integrer gpx_limit_import: max number of files in zip archive
|
||||
:<json integer gpx_limit_import: max number of files in zip archive
|
||||
:<json boolean is_registration_enabled: is registration enabled ?
|
||||
:<json integrer max_single_file_size: max size of a single file
|
||||
:<json integrer max_zip_file_size: max size of a zip archive
|
||||
:<json integrer max_users: max users allowed to register on instance
|
||||
:<json integer max_single_file_size: max size of a single file
|
||||
:<json integer max_zip_file_size: max size of a zip archive
|
||||
:<json integer max_users: max users allowed to register on instance
|
||||
|
||||
:reqheader Authorization: OAuth 2.0 Bearer Token
|
||||
|
||||
@@ -117,6 +117,10 @@ def update_application_config(auth_user_id: int) -> Union[Dict, HttpResponse]:
|
||||
if not config_data:
|
||||
return InvalidPayloadErrorResponse()
|
||||
|
||||
ret = verify_app_config(config_data)
|
||||
if ret:
|
||||
return InvalidPayloadErrorResponse(message=ret)
|
||||
|
||||
try:
|
||||
config = AppConfig.query.one()
|
||||
if 'gpx_limit_import' in config_data:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import os
|
||||
from typing import Tuple
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
from flask import Flask
|
||||
|
||||
@@ -49,3 +49,30 @@ def update_app_config_from_database(
|
||||
current_app.config[
|
||||
'is_registration_enabled'
|
||||
] = db_config.is_registration_enabled
|
||||
|
||||
|
||||
def verify_app_config(config_data: Dict) -> List:
|
||||
"""
|
||||
Verify if application config is valid.
|
||||
|
||||
If not, it returns not empty string
|
||||
"""
|
||||
ret = []
|
||||
if (
|
||||
'gpx_limit_import' in config_data
|
||||
and config_data['gpx_limit_import'] <= 0
|
||||
):
|
||||
ret.append('Max. files in a zip archive must be greater than 0')
|
||||
|
||||
if (
|
||||
'max_single_file_size' in config_data
|
||||
and config_data['max_single_file_size'] <= 0
|
||||
):
|
||||
ret.append('Max. size of uploaded files must be greater than 0')
|
||||
|
||||
if (
|
||||
'max_zip_file_size' in config_data
|
||||
and config_data['max_zip_file_size'] <= 0
|
||||
):
|
||||
ret.append('Max. size of zip archive must be greater than 0')
|
||||
return ret
|
||||
|
||||
Vendored
+3
-3
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.376b8924.chunk.css",
|
||||
"main.js": "/static/js/main.7c5c861a.chunk.js",
|
||||
"main.js.map": "/static/js/main.7c5c861a.chunk.js.map",
|
||||
"main.js": "/static/js/main.4387b246.chunk.js",
|
||||
"main.js.map": "/static/js/main.4387b246.chunk.js.map",
|
||||
"runtime-main.js": "/static/js/runtime-main.1240af94.js",
|
||||
"runtime-main.js.map": "/static/js/runtime-main.1240af94.js.map",
|
||||
"static/js/2.301144a0.chunk.js": "/static/js/2.301144a0.chunk.js",
|
||||
@@ -19,6 +19,6 @@
|
||||
"static/js/runtime-main.1240af94.js",
|
||||
"static/js/2.301144a0.chunk.js",
|
||||
"static/css/main.376b8924.chunk.css",
|
||||
"static/js/main.7c5c861a.chunk.js"
|
||||
"static/js/main.4387b246.chunk.js"
|
||||
]
|
||||
}
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="#000000"><link rel="manifest" href="/manifest.json"><link rel="shortcut icon" href="/favicon.ico"><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.1.7/css/fork-awesome.min.css" integrity="sha256-gsmEoJAws/Kd3CjuOQzLie5Q3yshhvmo7YNtBG7aaEY=" crossorigin="anonymous"><link rel="stylesheet" href="https://cdn.jsdelivr.net/foundation-icons/3.0/foundation-icons.min.css"><link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""><title>FitTrackee</title><link href="/static/css/main.376b8924.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script><script type="text/javascript">$(document).ready((function(){$("li.nav-item").click((function(){$("button.navbar-toggler").toggleClass("collapsed"),$("#navbarSupportedContent").toggleClass("show")}))}))</script><script>!function(e){function t(t){for(var n,i,l=t[0],f=t[1],a=t[2],p=0,s=[];p<l.length;p++)i=l[p],Object.prototype.hasOwnProperty.call(o,i)&&o[i]&&s.push(o[i][0]),o[i]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(c&&c(t);s.length;)s.shift()();return u.push.apply(u,a||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,l=1;l<r.length;l++){var f=r[l];0!==o[f]&&(n=!1)}n&&(u.splice(t--,1),e=i(i.s=r[0]))}return e}var n={},o={1:0},u=[];function i(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,i),r.l=!0,r.exports}i.m=e,i.c=n,i.d=function(e,t,r){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(i.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)i.d(r,n,function(t){return e[t]}.bind(null,n));return r},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="/";var l=this.webpackJsonpfittrackee_client=this.webpackJsonpfittrackee_client||[],f=l.push.bind(l);l.push=t,l=l.slice();for(var a=0;a<l.length;a++)t(l[a]);var c=f;r()}([])</script><script src="/static/js/2.301144a0.chunk.js"></script><script src="/static/js/main.7c5c861a.chunk.js"></script></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="#000000"><link rel="manifest" href="/manifest.json"><link rel="shortcut icon" href="/favicon.ico"><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.1.7/css/fork-awesome.min.css" integrity="sha256-gsmEoJAws/Kd3CjuOQzLie5Q3yshhvmo7YNtBG7aaEY=" crossorigin="anonymous"><link rel="stylesheet" href="https://cdn.jsdelivr.net/foundation-icons/3.0/foundation-icons.min.css"><link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""><title>FitTrackee</title><link href="/static/css/main.376b8924.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script><script type="text/javascript">$(document).ready((function(){$("li.nav-item").click((function(){$("button.navbar-toggler").toggleClass("collapsed"),$("#navbarSupportedContent").toggleClass("show")}))}))</script><script>!function(e){function t(t){for(var n,i,l=t[0],f=t[1],a=t[2],p=0,s=[];p<l.length;p++)i=l[p],Object.prototype.hasOwnProperty.call(o,i)&&o[i]&&s.push(o[i][0]),o[i]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(c&&c(t);s.length;)s.shift()();return u.push.apply(u,a||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,l=1;l<r.length;l++){var f=r[l];0!==o[f]&&(n=!1)}n&&(u.splice(t--,1),e=i(i.s=r[0]))}return e}var n={},o={1:0},u=[];function i(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,i),r.l=!0,r.exports}i.m=e,i.c=n,i.d=function(e,t,r){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(i.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)i.d(r,n,function(t){return e[t]}.bind(null,n));return r},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="/";var l=this.webpackJsonpfittrackee_client=this.webpackJsonpfittrackee_client||[],f=l.push.bind(l);l.push=t,l=l.slice();for(var a=0;a<l.length;a++)t(l[a]);var c=f;r()}([])</script><script src="/static/js/2.301144a0.chunk.js"></script><script src="/static/js/main.4387b246.chunk.js"></script></body></html>
|
||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -32,7 +32,10 @@ class HttpResponse(Response):
|
||||
|
||||
class GenericErrorResponse(HttpResponse):
|
||||
def __init__(
|
||||
self, status_code: int, message: str, status: Optional[str] = None
|
||||
self,
|
||||
status_code: int,
|
||||
message: Union[str, List],
|
||||
status: Optional[str] = None,
|
||||
) -> None:
|
||||
response = {
|
||||
'status': 'error' if status is None else status,
|
||||
@@ -46,7 +49,9 @@ class GenericErrorResponse(HttpResponse):
|
||||
|
||||
class InvalidPayloadErrorResponse(GenericErrorResponse):
|
||||
def __init__(
|
||||
self, message: Optional[str] = None, status: Optional[str] = None
|
||||
self,
|
||||
message: Optional[Union[str, List]] = None,
|
||||
status: Optional[str] = None,
|
||||
) -> None:
|
||||
message = 'Invalid payload.' if message is None else message
|
||||
super().__init__(status_code=400, message=message, status=status)
|
||||
|
||||
@@ -276,3 +276,105 @@ class TestUpdateConfig:
|
||||
'Max. size of zip archive must be equal or greater than max. size '
|
||||
'of uploaded files'
|
||||
) in data['message']
|
||||
|
||||
def test_it_raises_error_if_archive_max_size_equals_0(
|
||||
self, app_with_max_single_file_size: Flask, user_1_admin: User
|
||||
) -> None:
|
||||
client = app_with_max_single_file_size.test_client()
|
||||
resp_login = client.post(
|
||||
'/api/auth/login',
|
||||
data=json.dumps(
|
||||
dict(email='admin@example.com', password='12345678')
|
||||
),
|
||||
content_type='application/json',
|
||||
)
|
||||
|
||||
response = client.patch(
|
||||
'/api/config',
|
||||
content_type='application/json',
|
||||
data=json.dumps(
|
||||
dict(
|
||||
max_zip_file_size=0,
|
||||
)
|
||||
),
|
||||
headers=dict(
|
||||
Authorization='Bearer '
|
||||
+ json.loads(resp_login.data.decode())['auth_token']
|
||||
),
|
||||
)
|
||||
|
||||
data = json.loads(response.data.decode())
|
||||
assert response.status_code == 400
|
||||
assert 'error' in data['status']
|
||||
assert (
|
||||
'Max. size of zip archive must be greater than 0'
|
||||
in data['message']
|
||||
)
|
||||
|
||||
def test_it_raises_error_if_files_max_size_equals_0(
|
||||
self, app: Flask, user_1_admin: User
|
||||
) -> None:
|
||||
client = app.test_client()
|
||||
resp_login = client.post(
|
||||
'/api/auth/login',
|
||||
data=json.dumps(
|
||||
dict(email='admin@example.com', password='12345678')
|
||||
),
|
||||
content_type='application/json',
|
||||
)
|
||||
|
||||
response = client.patch(
|
||||
'/api/config',
|
||||
content_type='application/json',
|
||||
data=json.dumps(
|
||||
dict(
|
||||
max_single_file_size=0,
|
||||
)
|
||||
),
|
||||
headers=dict(
|
||||
Authorization='Bearer '
|
||||
+ json.loads(resp_login.data.decode())['auth_token']
|
||||
),
|
||||
)
|
||||
|
||||
data = json.loads(response.data.decode())
|
||||
assert response.status_code == 400
|
||||
assert 'error' in data['status']
|
||||
assert (
|
||||
'Max. size of uploaded files must be greater than 0'
|
||||
in data['message']
|
||||
)
|
||||
|
||||
def test_it_raises_error_if_gpx_limit_import_equals_0(
|
||||
self, app: Flask, user_1_admin: User
|
||||
) -> None:
|
||||
client = app.test_client()
|
||||
resp_login = client.post(
|
||||
'/api/auth/login',
|
||||
data=json.dumps(
|
||||
dict(email='admin@example.com', password='12345678')
|
||||
),
|
||||
content_type='application/json',
|
||||
)
|
||||
|
||||
response = client.patch(
|
||||
'/api/config',
|
||||
content_type='application/json',
|
||||
data=json.dumps(
|
||||
dict(
|
||||
gpx_limit_import=0,
|
||||
)
|
||||
),
|
||||
headers=dict(
|
||||
Authorization='Bearer '
|
||||
+ json.loads(resp_login.data.decode())['auth_token']
|
||||
),
|
||||
)
|
||||
|
||||
data = json.loads(response.data.decode())
|
||||
assert response.status_code == 400
|
||||
assert 'error' in data['status']
|
||||
assert (
|
||||
'Max. files in a zip archive must be greater than 0'
|
||||
in data['message']
|
||||
)
|
||||
|
||||
+15
-1
@@ -11,11 +11,16 @@ from fittrackee.application.utils import update_app_config_from_database
|
||||
def get_app_config(
|
||||
with_config: Optional[bool] = False,
|
||||
max_workouts: Optional[int] = None,
|
||||
max_single_file_size: Optional[int] = None,
|
||||
) -> Optional[AppConfig]:
|
||||
if with_config:
|
||||
config = AppConfig()
|
||||
config.gpx_limit_import = 10 if max_workouts is None else max_workouts
|
||||
config.max_single_file_size = 1 * 1024 * 1024
|
||||
config.max_single_file_size = (
|
||||
1 * 1024 * 1024
|
||||
if max_single_file_size is None
|
||||
else max_single_file_size
|
||||
)
|
||||
config.max_zip_file_size = 1 * 1024 * 1024 * 10
|
||||
config.max_users = 100
|
||||
db.session.add(config)
|
||||
@@ -27,6 +32,7 @@ def get_app_config(
|
||||
def get_app(
|
||||
with_config: Optional[bool] = False,
|
||||
max_workouts: Optional[int] = None,
|
||||
max_single_file_size: Optional[int] = None,
|
||||
) -> Generator:
|
||||
app = create_app()
|
||||
with app.app_context():
|
||||
@@ -64,6 +70,14 @@ def app_with_max_workouts(monkeypatch: pytest.MonkeyPatch) -> Generator:
|
||||
yield from get_app(with_config=True, max_workouts=2)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app_with_max_single_file_size(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> Generator:
|
||||
monkeypatch.setenv('EMAIL_URL', 'smtp://none:none@0.0.0.0:1025')
|
||||
yield from get_app(with_config=True, max_single_file_size=0)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app_no_config() -> Generator:
|
||||
yield from get_app(with_config=False)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import FitTrackeeGenericApi from '../fitTrackeeApi'
|
||||
import { history } from '../index'
|
||||
import { setError } from './index'
|
||||
import { generateIds } from '../utils'
|
||||
import { emptyMessages, setError } from './index'
|
||||
|
||||
export const setAppConfig = data => ({
|
||||
type: 'SET_APP_CONFIG',
|
||||
@@ -12,6 +13,8 @@ export const setAppStats = data => ({
|
||||
data,
|
||||
})
|
||||
|
||||
const SetAppErrors = messages => ({ type: 'APP_ERRORS', messages })
|
||||
|
||||
export const getAppData = target => dispatch =>
|
||||
FitTrackeeGenericApi.getData(target)
|
||||
.then(ret => {
|
||||
@@ -27,14 +30,18 @@ export const getAppData = target => dispatch =>
|
||||
})
|
||||
.catch(error => dispatch(setError(`application|${error}`)))
|
||||
|
||||
export const updateAppConfig = formData => dispatch =>
|
||||
export const updateAppConfig = formData => dispatch => {
|
||||
dispatch(emptyMessages())
|
||||
FitTrackeeGenericApi.updateData('config', formData)
|
||||
.then(ret => {
|
||||
if (ret.status === 'success') {
|
||||
dispatch(setAppConfig(ret.data))
|
||||
history.push('/admin/application')
|
||||
} else if (Array.isArray(ret.message)) {
|
||||
dispatch(SetAppErrors(generateIds(ret.message)))
|
||||
} else {
|
||||
dispatch(setError(`application|${ret.message}`))
|
||||
dispatch(setError(ret.message))
|
||||
}
|
||||
})
|
||||
.catch(error => dispatch(setError(`application|${error}`)))
|
||||
}
|
||||
|
||||
@@ -3,11 +3,16 @@ import i18next from 'i18next'
|
||||
import FitTrackeeApi from '../fitTrackeeApi/index'
|
||||
import { history } from '../index'
|
||||
|
||||
export const emptyMessages = () => ({
|
||||
type: 'CLEAN_ALL_MESSAGES',
|
||||
})
|
||||
|
||||
export const setData = (target, data) => ({
|
||||
type: 'SET_DATA',
|
||||
data,
|
||||
target,
|
||||
})
|
||||
|
||||
export const setPaginatedData = (target, data, pagination) => ({
|
||||
type: 'SET_PAGINATED_DATA',
|
||||
data,
|
||||
@@ -51,7 +56,7 @@ export const getOrUpdateData = (
|
||||
dispatch(setLoading(false))
|
||||
return dispatch(setError(`${target}|Incorrect id`))
|
||||
}
|
||||
dispatch(setError(''))
|
||||
dispatch(emptyMessages())
|
||||
return FitTrackeeApi[action](target, data)
|
||||
.then(ret => {
|
||||
if (ret.status === 'success') {
|
||||
|
||||
@@ -48,13 +48,16 @@ class AdminApplication extends React.Component {
|
||||
isInEdition,
|
||||
loadAppConfig,
|
||||
message,
|
||||
messages,
|
||||
onHandleConfigFormSubmit,
|
||||
t,
|
||||
} = this.props
|
||||
const { formData } = this.state
|
||||
return (
|
||||
<div>
|
||||
{message && <Message message={message} t={t} />}
|
||||
{(message || messages) && (
|
||||
<Message message={message} messages={messages} t={t} />
|
||||
)}
|
||||
{Object.keys(formData).length > 0 && (
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
@@ -209,6 +212,7 @@ class AdminApplication extends React.Component {
|
||||
export default connect(
|
||||
state => ({
|
||||
message: state.message,
|
||||
messages: state.messages,
|
||||
}),
|
||||
dispatch => ({
|
||||
loadAppConfig: () => {
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
"Invalid credentials.": "Invalid credentials.",
|
||||
"Invalid payload.": "Invalid payload.",
|
||||
"Invalid token. Please log in again.": "Invalid token. Please log in again.",
|
||||
"Max. files in a zip archive must be greater than 0": "Max. files in a zip archive must be greater than 0",
|
||||
"Max. size of uploaded files must be greater than 0": "Max. size of uploaded files must be greater than 0",
|
||||
"Max. size of zip archive must be equal or greater than max. size of uploaded files": "Max. size of zip archive must be equal or greater than max. size of uploaded files",
|
||||
"Max. size of zip archive must be greater than 0": "Max. size of zip archive must be greater than 0",
|
||||
"No file part.": "No file part.",
|
||||
"No picture.": "No picture.",
|
||||
"No selected file.": "No selected file.",
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
"Invalid credentials.": "Identifiants invalides.",
|
||||
"Invalid payload.": "Données incorrectes.",
|
||||
"Invalid token. Please log in again.": "Jeton invalide. Merci de vous reconnecter.",
|
||||
"Max. files in a zip archive must be greater than 0": "Le nombre max. de fichiers dans une archive doit être supérieur à 0",
|
||||
"Max. size of uploaded files must be greater than 0": "La taille max. des fichiers doit être supérieure à 0",
|
||||
"Max. size of zip archive must be equal or greater than max. size of uploaded files": "La taille max. d'une archive doit être supérieure ou égale à la taille max. d'un fichier",
|
||||
"Max. size of zip archive must be greater than 0": "La taille max. d'une archive doit être supérieure à 0",
|
||||
"No file part.": "Pas de fichier fourni.",
|
||||
"No picture.": "Pas d'image.",
|
||||
"No selected file.": "Pas de fichier sélectionné.",
|
||||
|
||||
@@ -108,6 +108,7 @@ const message = (state = initial.message, action) => {
|
||||
case 'PICTURE_ERROR':
|
||||
case 'SET_ERROR':
|
||||
return action.message
|
||||
case 'CLEAN_ALL_MESSAGES':
|
||||
case 'LOGOUT':
|
||||
case 'PROFILE_SUCCESS':
|
||||
case 'SET_APP_CONFIG':
|
||||
@@ -122,7 +123,9 @@ const message = (state = initial.message, action) => {
|
||||
const messages = (state = initial.messages, action) => {
|
||||
switch (action.type) {
|
||||
case 'AUTH_ERRORS':
|
||||
case 'APP_ERRORS':
|
||||
return action.messages
|
||||
case 'CLEAN_ALL_MESSAGES':
|
||||
case 'LOGOUT':
|
||||
case 'PROFILE_SUCCESS':
|
||||
case '@@router/LOCATION_CHANGE':
|
||||
|
||||
Reference in New Issue
Block a user