react-admin-base-bootstrap 0.7.3 → 0.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/main.css +4 -0
- package/lib/esm/Components/BootstrapDataTable.js +30 -29
- package/lib/esm/Components/DefaultValidatorOptions.d.ts +3 -0
- package/lib/esm/Components/DefaultValidatorOptions.js +24 -0
- package/lib/esm/Components/ErrorBoundary.d.ts +4 -2
- package/lib/esm/Components/LanguageProvider.d.ts +4 -3
- package/lib/esm/Components/LanguageProvider.js +17 -14
- package/lib/esm/Components/PasswordInput.d.ts +11 -0
- package/lib/esm/Components/PasswordInput.js +39 -0
- package/lib/esm/Components/ThemeProvider.js +2 -11
- package/lib/esm/i18n/de.json +7 -0
- package/lib/esm/i18n/en.json +9 -1
- package/lib/esm/i18n/tr.json +7 -0
- package/lib/esm/index.d.ts +3 -1
- package/lib/esm/index.js +3 -1
- package/package.json +13 -10
- package/src/Components/BootstrapDataTable.tsx +45 -43
- package/src/Components/DefaultValidatorOptions.tsx +29 -0
- package/src/Components/ErrorBoundary.tsx +1 -1
- package/src/Components/LanguageProvider.tsx +20 -16
- package/src/Components/PasswordInput.tsx +93 -0
- package/src/Components/ThemeProvider.tsx +1 -14
- package/src/i18n/de.json +7 -0
- package/src/i18n/en.json +9 -1
- package/src/i18n/tr.json +7 -0
- package/src/index.ts +4 -0
package/assets/main.css
CHANGED
|
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
|
11
|
-
import { DataContextProvider, useAuth, useDataTable } from 'react-admin-base';
|
|
11
|
+
import { DataContextProvider, RefreshScope, useAuth, useDataTable } from 'react-admin-base';
|
|
12
12
|
import { FormattedMessage, useIntl } from "react-intl";
|
|
13
13
|
import { Link } from 'react-router-dom';
|
|
14
14
|
import { Alert, Button, Card, CardFooter, CardHeader, Col, Input, Row, Table } from 'reactstrap';
|
|
@@ -80,7 +80,7 @@ export function Column(props) {
|
|
|
80
80
|
export default function BootstrapTable({ url, bordered, noStrip, defaultParams, add, children, innerRef, body }) {
|
|
81
81
|
var state = useState(Object.assign({ sort: 'id' }, defaultParams));
|
|
82
82
|
const [params, setParams] = state;
|
|
83
|
-
const [page, lastPage, setPage, data, itemPerPage, setItemPerPage] = useDataTable(url, params, body);
|
|
83
|
+
const [page, lastPage, setPage, data, itemPerPage, setItemPerPage, update] = useDataTable(url, params, body);
|
|
84
84
|
const intl = useIntl();
|
|
85
85
|
const [api] = useAuth();
|
|
86
86
|
var ref = useRef(defaultParams);
|
|
@@ -111,31 +111,32 @@ export default function BootstrapTable({ url, bordered, noStrip, defaultParams,
|
|
|
111
111
|
return React.createElement(Card, null,
|
|
112
112
|
React.createElement(DataTableContext.Provider, { value: state },
|
|
113
113
|
React.createElement(DataContextProvider, { value: fetchData },
|
|
114
|
-
React.createElement(
|
|
115
|
-
React.createElement(
|
|
116
|
-
|
|
117
|
-
React.createElement(
|
|
118
|
-
React.createElement(
|
|
119
|
-
|
|
120
|
-
React.createElement(
|
|
121
|
-
React.createElement(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
React.createElement(
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
React.createElement(
|
|
140
|
-
React.createElement(
|
|
114
|
+
React.createElement(RefreshScope, { update: update },
|
|
115
|
+
React.createElement(CardHeader, null,
|
|
116
|
+
React.createElement(Row, null,
|
|
117
|
+
add && React.createElement(Col, { xs: "12", md: "2" },
|
|
118
|
+
React.createElement(Link, { to: add, className: "btn btn-primary font-xl d-block" },
|
|
119
|
+
React.createElement("i", { className: "fa fa-plus" }))),
|
|
120
|
+
React.createElement(Col, { md: "2" },
|
|
121
|
+
React.createElement(Input, { type: "select", value: itemPerPage.toString(), onChange: a => setItemPerPage(+a.currentTarget.value) },
|
|
122
|
+
React.createElement("option", { value: "1" }, "1"),
|
|
123
|
+
React.createElement("option", { value: "20" }, "20"),
|
|
124
|
+
React.createElement("option", { value: "50" }, "50"),
|
|
125
|
+
React.createElement("option", { value: "100" }, "100"),
|
|
126
|
+
React.createElement("option", { value: "150" }, "150"),
|
|
127
|
+
React.createElement("option", { value: "200" }, "200"),
|
|
128
|
+
React.createElement("option", { value: "-1" }, intl.formatMessage({ id: "ALL" })))),
|
|
129
|
+
children[2],
|
|
130
|
+
React.createElement(Col, { md: "3", className: "ms-auto" },
|
|
131
|
+
React.createElement(Input, { placeholder: intl.formatMessage({ id: "SEARCH" }), type: "text", value: params.query || '', onChange: e => setParams(Object.assign(Object.assign({}, params), { query: e.currentTarget.value })) })))),
|
|
132
|
+
data === null ? React.createElement(Alert, { className: "text-center mb-0 mx-3 ", color: "warning" },
|
|
133
|
+
React.createElement("i", { className: "fas fa-spinner fa-spin" })) : !data.length ? React.createElement(Alert, { className: "text-center mx-3", color: "danger" },
|
|
134
|
+
React.createElement("i", { className: "far fa-times-circle" }),
|
|
135
|
+
" ",
|
|
136
|
+
React.createElement(FormattedMessage, { id: "NO_DATA_IS_AVAILABLE" })) : React.createElement(Table, { hover: true, bordered: bordered, striped: !noStrip, responsive: true, size: "md", className: "mb-0 dataTable" },
|
|
137
|
+
children[0],
|
|
138
|
+
React.createElement("tbody", null, data && data.map(children[1].props.children))),
|
|
139
|
+
lastPage > 1 && React.createElement(CardFooter, null,
|
|
140
|
+
React.createElement("nav", null,
|
|
141
|
+
React.createElement(BootstrapPagination, { currentPage: page, pageCount: lastPage, onPageChange: index => setPage(index) })))))));
|
|
141
142
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
|
+
import { ValidatorOptionProvider } from "react-admin-base";
|
|
3
|
+
import { useIntl } from "react-intl";
|
|
4
|
+
import zxcvbn from 'zxcvbn';
|
|
5
|
+
export default function DefaultValidatorOptions({ children }) {
|
|
6
|
+
const intl = useIntl();
|
|
7
|
+
const options = useMemo(() => ({
|
|
8
|
+
validators: {
|
|
9
|
+
password: {
|
|
10
|
+
message: intl.formatMessage({ id: 'PASSWORD_NOMATCH' }),
|
|
11
|
+
rule: function (val, params) {
|
|
12
|
+
return val == params[0];
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
securepassword: {
|
|
16
|
+
message: intl.formatMessage({ id: 'INSECURE_PASSWORD' }),
|
|
17
|
+
rule: function (val, params) {
|
|
18
|
+
return !val || (zxcvbn(val, []).score >= 2);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}), [intl]);
|
|
23
|
+
return React.createElement(ValidatorOptionProvider, { value: options }, children);
|
|
24
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
export default class ErrorBoundary extends React.Component
|
|
2
|
+
export default class ErrorBoundary extends React.Component<{
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
}> {
|
|
3
5
|
state: {
|
|
4
6
|
hasError: boolean;
|
|
5
7
|
error: null;
|
|
@@ -8,5 +10,5 @@ export default class ErrorBoundary extends React.Component {
|
|
|
8
10
|
hasError: boolean;
|
|
9
11
|
error: any;
|
|
10
12
|
};
|
|
11
|
-
render(): React.
|
|
13
|
+
render(): string | number | boolean | JSX.Element | React.ReactFragment | null | undefined;
|
|
12
14
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export declare function useLanguage(): any;
|
|
2
|
-
export default function LanguageProvider({ defaultLanguage, languages, children }: {
|
|
2
|
+
export default function LanguageProvider({ defaultLanguage, languages, loader, children }: {
|
|
3
3
|
defaultLanguage: any;
|
|
4
4
|
languages: any;
|
|
5
|
+
loader: any;
|
|
5
6
|
children: any;
|
|
6
|
-
}): JSX.Element;
|
|
7
|
-
export declare function LanguageSwitcher(): JSX.Element;
|
|
7
|
+
}): JSX.Element | null;
|
|
8
|
+
export declare function LanguageSwitcher(): JSX.Element | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React, { useContext,
|
|
2
|
-
import { useApp } from 'react-admin-base';
|
|
1
|
+
import React, { useContext, useMemo, useState } from 'react';
|
|
2
|
+
import { useApp, useLocalStorage } from 'react-admin-base';
|
|
3
3
|
import { IntlProvider } from 'react-intl';
|
|
4
4
|
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
|
|
5
5
|
import enMessages from '../i18n/en.json';
|
|
@@ -14,29 +14,32 @@ const LanguageContext = React.createContext(null);
|
|
|
14
14
|
export function useLanguage() {
|
|
15
15
|
return useContext(LanguageContext);
|
|
16
16
|
}
|
|
17
|
-
export default function LanguageProvider({ defaultLanguage, languages, children }) {
|
|
17
|
+
export default function LanguageProvider({ defaultLanguage, languages, loader, children }) {
|
|
18
18
|
const app = useApp();
|
|
19
|
-
const preferredLanguage = (navigator.languages && navigator.languages[0]) ||
|
|
20
|
-
|
|
21
|
-
const [lang, setLang] = useReducer((oldValue, newValue) => {
|
|
22
|
-
localStorage.setItem(app.id + "_" + 'language', newValue);
|
|
23
|
-
return newValue;
|
|
24
|
-
}, localStorage.getItem(app.id + "_" + 'language') || null);
|
|
19
|
+
const preferredLanguage = (navigator.languages && navigator.languages[0]) || navigator.language;
|
|
20
|
+
const [lang, setLang] = useLocalStorage(app.id + "_language");
|
|
25
21
|
const activeLanguageKey = (!!lang && languages[lang] && lang) || (languages[preferredLanguage] && preferredLanguage) || (languages[defaultLanguage] && defaultLanguage);
|
|
26
22
|
const activeLanguage = languages[activeLanguageKey];
|
|
27
|
-
const messages = useMemo(() => (Object.assign(Object.assign({}, (_languages[activeLanguageKey] || _languages.en)), activeLanguage.messages)), [activeLanguage]);
|
|
28
23
|
const value = useMemo(() => [activeLanguage, languages, setLang], [activeLanguage, languages, setLang]);
|
|
24
|
+
const originalMessages = (loader && loader(activeLanguage)) || activeLanguage.messages;
|
|
25
|
+
const messages = useMemo(() => originalMessages && (Object.assign(Object.assign({}, (_languages[activeLanguageKey] || _languages.en)), originalMessages)), [originalMessages, activeLanguage]);
|
|
26
|
+
if (!messages)
|
|
27
|
+
return null;
|
|
29
28
|
return React.createElement(IntlProvider, { locale: activeLanguageKey, messages: messages },
|
|
30
29
|
React.createElement(LanguageContext.Provider, { value: value }, children));
|
|
31
30
|
}
|
|
32
31
|
export function LanguageSwitcher() {
|
|
33
32
|
const [show, setShow] = useState(false);
|
|
34
33
|
const [activeLang, languages, setLanguage] = useLanguage();
|
|
34
|
+
if (Object.keys(languages).length <= 1)
|
|
35
|
+
return null;
|
|
35
36
|
return React.createElement(Dropdown, { isOpen: show, toggle: () => setShow(!show) },
|
|
36
|
-
React.createElement(DropdownToggle, { className: "nav-flag
|
|
37
|
-
React.createElement("img", { width: "20", src: activeLang.icon, alt: activeLang.name })
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
React.createElement(DropdownToggle, { className: "nav-flag", nav: true, caret: true },
|
|
38
|
+
activeLang.icon && React.createElement("img", { width: "20", className: "me-1", src: activeLang.icon, alt: activeLang.name }),
|
|
39
|
+
" ",
|
|
40
|
+
activeLang.name),
|
|
41
|
+
React.createElement(DropdownMenu, null, Object.entries(languages).map(([key, value]) => React.createElement(DropdownItem, { key: key, active: activeLang === value, onClick: () => setLanguage(key) },
|
|
42
|
+
value.icon && React.createElement("img", { width: "20", className: "me-1", src: value.icon, alt: value.name }),
|
|
40
43
|
" ",
|
|
41
44
|
React.createElement("span", { className: "align-middle" }, value.name)))));
|
|
42
45
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface PasswordInputParams {
|
|
2
|
+
value?: string;
|
|
3
|
+
onChange: (str: string) => any;
|
|
4
|
+
className?: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
icon?: string;
|
|
7
|
+
required?: boolean;
|
|
8
|
+
placeholder?: string;
|
|
9
|
+
}
|
|
10
|
+
export default function PasswordInput({ value, onChange, className, disabled, icon, required, placeholder }: PasswordInputParams): JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React, { useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { FormattedMessage, useIntl } from "react-intl";
|
|
3
|
+
import PasswordStrengthBar from "react-password-strength-bar";
|
|
4
|
+
import { FormGroup, Label, Input } from 'reactstrap';
|
|
5
|
+
import { Validator } from "./Validator";
|
|
6
|
+
function BootstrapPasswordInput({ className, value, onChange, disabled, placeholder }) {
|
|
7
|
+
const intl = useIntl();
|
|
8
|
+
const short = intl.formatMessage({ id: "PASSWORD_SHORT" });
|
|
9
|
+
const bad = intl.formatMessage({ id: "PASSWORD_BAD" });
|
|
10
|
+
const okay = intl.formatMessage({ id: "PASSWORD_OKAY" });
|
|
11
|
+
const good = intl.formatMessage({ id: "PASSWORD_GOOD" });
|
|
12
|
+
const perfect = intl.formatMessage({ id: "PASSWORD_PERFECT" });
|
|
13
|
+
const scoreWords = useMemo(() => [short, bad, okay, good, perfect], [short, bad, okay, good, perfect]);
|
|
14
|
+
return React.createElement(React.Fragment, null,
|
|
15
|
+
React.createElement(Input, { className: className, type: "password", value: value || '', onChange: a => onChange(a.currentTarget.value), disabled: disabled, placeholder: placeholder }),
|
|
16
|
+
React.createElement(PasswordStrengthBar, { className: "password-str-bar", password: value || '', scoreWords: scoreWords, shortScoreWord: short }));
|
|
17
|
+
}
|
|
18
|
+
export default function PasswordInput({ value, onChange, className, disabled, icon, required, placeholder }) {
|
|
19
|
+
const [password2, setPassword2] = useState('');
|
|
20
|
+
const iconElem = icon && React.createElement("i", { className: icon });
|
|
21
|
+
useEffect(function () {
|
|
22
|
+
if (!value) {
|
|
23
|
+
setPassword2('');
|
|
24
|
+
}
|
|
25
|
+
}, [value, setPassword2]);
|
|
26
|
+
return React.createElement(React.Fragment, null,
|
|
27
|
+
React.createElement(FormGroup, { className: className },
|
|
28
|
+
iconElem,
|
|
29
|
+
React.createElement(Label, null,
|
|
30
|
+
React.createElement(FormattedMessage, { id: "PASSWORD" })),
|
|
31
|
+
React.createElement(Validator, { name: "password", type: [required && "required", "securepassword"].filter(a => !!a) },
|
|
32
|
+
React.createElement(BootstrapPasswordInput, { value: value, onChange: onChange, disabled: disabled, placeholder: placeholder }))),
|
|
33
|
+
!!(required || value) && React.createElement(FormGroup, { className: className },
|
|
34
|
+
iconElem,
|
|
35
|
+
React.createElement(Label, null,
|
|
36
|
+
React.createElement(FormattedMessage, { id: "PASSWORD_AGAIN" })),
|
|
37
|
+
React.createElement(Validator, { name: "password2", type: [(required || value) && "required", { password: value || '' }].filter(a => !!a) },
|
|
38
|
+
React.createElement(Input, { type: "password", value: password2 || '', onChange: a => setPassword2(a.currentTarget.value), disabled: disabled }))));
|
|
39
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React, { createContext, useContext, useEffect, useMemo
|
|
2
|
-
import {
|
|
1
|
+
import React, { createContext, useContext, useEffect, useMemo } from "react";
|
|
2
|
+
import { useLocalStorage } from "react-admin-base";
|
|
3
3
|
const ThemeContext = createContext(null);
|
|
4
4
|
const AllThemesContext = createContext(null);
|
|
5
5
|
export function useTheme() {
|
|
@@ -8,15 +8,6 @@ export function useTheme() {
|
|
|
8
8
|
export function useAllThemes() {
|
|
9
9
|
return useContext(AllThemesContext);
|
|
10
10
|
}
|
|
11
|
-
function useLocalStorage(key) {
|
|
12
|
-
const app = useApp();
|
|
13
|
-
const _key = app.id + '_' + key;
|
|
14
|
-
const previousValue = useMemo(() => localStorage.getItem(_key), [_key]);
|
|
15
|
-
return useReducer((_, newValue) => {
|
|
16
|
-
localStorage.setItem(_key, newValue);
|
|
17
|
-
return newValue;
|
|
18
|
-
}, previousValue);
|
|
19
|
-
}
|
|
20
11
|
export default function ThemeProvider({ themes, defaultTheme, children }) {
|
|
21
12
|
const state = useLocalStorage('theme');
|
|
22
13
|
const [theme, setTheme] = state;
|
package/lib/esm/i18n/de.json
CHANGED
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
"USERNAME": "Benutzername",
|
|
5
5
|
"PASSWORD": "Passwort",
|
|
6
6
|
"FORGOT_PASSWORD": "Ich habe mein Passwort vergessen",
|
|
7
|
+
"INSECURE_PASSWORD": "Passwort ist nicht sicher",
|
|
8
|
+
"PASSWORD_NOMATCH": "Passwort ist falsch",
|
|
9
|
+
"PASSWORD_SHORT": "zu kurz",
|
|
10
|
+
"PASSWORD_BAD": "schlecht",
|
|
11
|
+
"PASSWORD_OKAY": "okay",
|
|
12
|
+
"PASSWORD_GOOD": "gut",
|
|
13
|
+
"PASSWORD_PERFECT": "perfekt",
|
|
7
14
|
"LOGIN": "Einloggen",
|
|
8
15
|
"LOGIN_HEAD": "Anmeldebereich",
|
|
9
16
|
"SUBMIT": "Absenden",
|
package/lib/esm/i18n/en.json
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
"ENTITY.CANCEL": "Cancel",
|
|
4
4
|
"USERNAME": "Username",
|
|
5
5
|
"PASSWORD": "Password",
|
|
6
|
+
"PASSWORD_AGAIN": "Password (again)",
|
|
7
|
+
"PASSWORD_SHORT": "too short",
|
|
8
|
+
"PASSWORD_BAD": "bad",
|
|
9
|
+
"PASSWORD_OKAY": "okay",
|
|
10
|
+
"PASSWORD_GOOD": "good",
|
|
11
|
+
"PASSWORD_PERFECT": "perfect",
|
|
12
|
+
"INSECURE_PASSWORD": "Password is not secure",
|
|
13
|
+
"PASSWORD_NOMATCH": "Passwords does not match",
|
|
6
14
|
"FORGOT_PASSWORD": "I forgot my password",
|
|
7
15
|
"LOGIN": "Login",
|
|
8
16
|
"LOGIN_HEAD": "Login Area",
|
|
@@ -12,7 +20,7 @@
|
|
|
12
20
|
"EMAIL": "Email",
|
|
13
21
|
"AUTH_CODE": "Authorization Code",
|
|
14
22
|
"ENTER_AUTH_CODE": "Please enter the verification code that we sent to {email}.",
|
|
15
|
-
"CHANGE_EMAIL": "Not your e-mail? <
|
|
23
|
+
"CHANGE_EMAIL": "Not your e-mail? <a>Sent to a new email address</a>.",
|
|
16
24
|
"PASSWORD_REPEAT": "Password (again)",
|
|
17
25
|
"VALIDATION.ERROR": "Entity has following errors:",
|
|
18
26
|
"ENTITY.SAVED": "Changes are saved.",
|
package/lib/esm/i18n/tr.json
CHANGED
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
"USERNAME": "Kullanıcı Adı",
|
|
5
5
|
"PASSWORD": "Şifre",
|
|
6
6
|
"FORGOT_PASSWORD": "Şifremi unuttum",
|
|
7
|
+
"INSECURE_PASSWORD": "Şifre güvenli değil",
|
|
8
|
+
"PASSWORD_NOMATCH": "Şifreler uyuşmuyor",
|
|
9
|
+
"PASSWORD_SHORT": "çok kısa",
|
|
10
|
+
"PASSWORD_BAD": "kötü",
|
|
11
|
+
"PASSWORD_OKAY": "idare eder",
|
|
12
|
+
"PASSWORD_GOOD": "iyi",
|
|
13
|
+
"PASSWORD_PERFECT": "harika",
|
|
7
14
|
"SUBMIT": "Gönder",
|
|
8
15
|
"LOGIN": "Giriş",
|
|
9
16
|
"LOGIN_HEAD": "Oturum Açma Alanı",
|
package/lib/esm/index.d.ts
CHANGED
|
@@ -18,4 +18,6 @@ import { useMenuState, useIsMobile } from './Components/MenuState';
|
|
|
18
18
|
import TopProgressBar from './Components/TopProgressBar';
|
|
19
19
|
import ThemeProvider, { useTheme, useAllThemes } from './Components/ThemeProvider';
|
|
20
20
|
import StepList, { StepItem } from './Components/StepList';
|
|
21
|
-
|
|
21
|
+
import PasswordInput from './Components/PasswordInput';
|
|
22
|
+
import DefaultValidatorOptions from './Components/DefaultValidatorOptions';
|
|
23
|
+
export { ThemeProvider, useTheme, useAllThemes, useIsMobile, useMenuState, DefaultValidatorOptions, PasswordInput, StepList, StepItem, TopProgressBar, CRUD, ModalEntityEditor, CRUDActions, Relative, ApiSelect, Preview, ExcelExportButton, ExternalLoginButton, SingleFilePicker, MultiFilePicker, ImagePicker, BootstrapTable, EntityEditor, GoToTop, Validator, ValueValidator, ValidationErrors, LoadingButton, BootstrapDataTable, IdColumn, Column, ActionsColumn, Actions, useDataTableContext, LanguageProvider, useLanguage, LanguageSwitcher, ErrorBoundary, CheckBox };
|
package/lib/esm/index.js
CHANGED
|
@@ -18,4 +18,6 @@ import { useMenuState, useIsMobile } from './Components/MenuState';
|
|
|
18
18
|
import TopProgressBar from './Components/TopProgressBar';
|
|
19
19
|
import ThemeProvider, { useTheme, useAllThemes } from './Components/ThemeProvider';
|
|
20
20
|
import StepList, { StepItem } from './Components/StepList';
|
|
21
|
-
|
|
21
|
+
import PasswordInput from './Components/PasswordInput';
|
|
22
|
+
import DefaultValidatorOptions from './Components/DefaultValidatorOptions';
|
|
23
|
+
export { ThemeProvider, useTheme, useAllThemes, useIsMobile, useMenuState, DefaultValidatorOptions, PasswordInput, StepList, StepItem, TopProgressBar, CRUD, ModalEntityEditor, CRUDActions, Relative, ApiSelect, Preview, ExcelExportButton, ExternalLoginButton, SingleFilePicker, MultiFilePicker, ImagePicker, BootstrapTable, EntityEditor, GoToTop, Validator, ValueValidator, ValidationErrors, LoadingButton, BootstrapDataTable, IdColumn, Column, ActionsColumn, Actions, useDataTableContext, LanguageProvider, useLanguage, LanguageSwitcher, ErrorBoundary, CheckBox };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-admin-base-bootstrap",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.6",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
@@ -25,29 +25,32 @@
|
|
|
25
25
|
"delay": "100"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"react": "^18.
|
|
28
|
+
"react": "^18.2.0",
|
|
29
|
+
"react-dom": "^18.2.0",
|
|
29
30
|
"react-intl": "^5.21.0",
|
|
30
31
|
"react-router-dom": "^6.3.0"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
|
-
"@emotion/react": "^11.
|
|
34
|
+
"@emotion/react": "^11.9.3",
|
|
34
35
|
"@fortawesome/fontawesome-free": "^6.1.1",
|
|
35
36
|
"bootstrap": "^5.1.3",
|
|
36
37
|
"file-dialog": "^0.0.8",
|
|
37
38
|
"modal-cropper": "^1.2.3",
|
|
38
39
|
"nprogress": "^0.2.0",
|
|
39
40
|
"prettysize": "^2.0.0",
|
|
40
|
-
"react-admin-base": "^0.7.
|
|
41
|
+
"react-admin-base": "^0.7.3",
|
|
42
|
+
"react-password-strength-bar": "^0.4.1",
|
|
41
43
|
"react-responsive": "^8.2.0",
|
|
42
|
-
"react-select": "^5.
|
|
43
|
-
"reactstrap": "^9.
|
|
44
|
+
"react-select": "^5.3.2",
|
|
45
|
+
"reactstrap": "^9.1.1",
|
|
44
46
|
"rewire": "^6.0.0",
|
|
45
|
-
"sweetalert2": "^11.4.
|
|
47
|
+
"sweetalert2": "^11.4.17"
|
|
46
48
|
},
|
|
47
49
|
"devDependencies": {
|
|
50
|
+
"@types/react": "^18.0.12",
|
|
48
51
|
"cross-env": "^7.0.3",
|
|
49
|
-
"nodemon": "^2.0.
|
|
50
|
-
"react-intl": "^
|
|
51
|
-
"typescript": "^4.
|
|
52
|
+
"nodemon": "^2.0.16",
|
|
53
|
+
"react-intl": "^6.0.4",
|
|
54
|
+
"typescript": "^4.7.3"
|
|
52
55
|
}
|
|
53
56
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { DataContextProvider, useAuth, useDataTable } from 'react-admin-base';
|
|
2
|
+
import { DataContextProvider, RefreshScope, useAuth, useDataTable } from 'react-admin-base';
|
|
3
3
|
import { FormattedMessage, useIntl } from "react-intl";
|
|
4
4
|
import { Link } from 'react-router-dom';
|
|
5
5
|
import { Alert, Button, Card, CardFooter, CardHeader, Col, Input, Row, Table } from 'reactstrap';
|
|
@@ -77,7 +77,7 @@ export function Column(props) {
|
|
|
77
77
|
export default function BootstrapTable({url, bordered, noStrip, defaultParams, add, children, innerRef, body}: any) {
|
|
78
78
|
var state = useState({sort: 'id', ...defaultParams});
|
|
79
79
|
const [params, setParams] = state;
|
|
80
|
-
const [page, lastPage, setPage, data, itemPerPage, setItemPerPage] = useDataTable(url, params, body);
|
|
80
|
+
const [page, lastPage, setPage, data, itemPerPage, setItemPerPage, update] = useDataTable(url, params, body);
|
|
81
81
|
const intl = useIntl();
|
|
82
82
|
const [ api ] = useAuth();
|
|
83
83
|
|
|
@@ -98,7 +98,7 @@ export default function BootstrapTable({url, bordered, noStrip, defaultParams, a
|
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
100
|
}, [setParams, innerRef]);
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
const fetchData = useCallback(async function(extraParams) {
|
|
103
103
|
if (body) {
|
|
104
104
|
const data = await api.tokenized.post(url, body, { params: { ...params, ...(extraParams || {}) } });
|
|
@@ -112,47 +112,49 @@ export default function BootstrapTable({url, bordered, noStrip, defaultParams, a
|
|
|
112
112
|
return <Card>
|
|
113
113
|
<DataTableContext.Provider value={state}>
|
|
114
114
|
<DataContextProvider value={fetchData}>
|
|
115
|
-
<
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
<
|
|
120
|
-
<
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
115
|
+
<RefreshScope update={update}>
|
|
116
|
+
<CardHeader>
|
|
117
|
+
<Row>
|
|
118
|
+
{add && <Col xs="12" md="2"><Link to={add} className="btn btn-primary font-xl d-block"><i className="fa fa-plus"/></Link></Col>}
|
|
119
|
+
<Col md="2">
|
|
120
|
+
<Input type="select" value={itemPerPage.toString()} onChange={a => setItemPerPage(+a.currentTarget.value)}>
|
|
121
|
+
<option value="1">1</option>
|
|
122
|
+
<option value="20">20</option>
|
|
123
|
+
<option value="50">50</option>
|
|
124
|
+
<option value="100">100</option>
|
|
125
|
+
<option value="150">150</option>
|
|
126
|
+
<option value="200">200</option>
|
|
127
|
+
<option value="-1">{intl.formatMessage({id: "ALL"})}</option>
|
|
128
|
+
</Input>
|
|
129
|
+
</Col>
|
|
130
|
+
{children[2]}
|
|
131
|
+
<Col md="3" className="ms-auto">
|
|
132
|
+
<Input
|
|
133
|
+
placeholder={intl.formatMessage({id: "SEARCH"})} type="text"
|
|
134
|
+
value={params.query || ''}
|
|
135
|
+
onChange={e => setParams({...params, query: e.currentTarget.value})}
|
|
136
|
+
/>
|
|
137
|
+
</Col>
|
|
138
|
+
</Row>
|
|
139
|
+
</CardHeader>
|
|
140
|
+
{data === null ? <Alert className="text-center mb-0 mx-3 " color="warning"><i className="fas fa-spinner fa-spin"></i></Alert> : !data.length ? <Alert className="text-center mx-3" color="danger">
|
|
141
|
+
<i className="far fa-times-circle"></i> <FormattedMessage id="NO_DATA_IS_AVAILABLE"/>
|
|
142
|
+
</Alert> : <Table hover bordered={bordered} striped={!noStrip} responsive size="md" className="mb-0 dataTable">
|
|
143
|
+
{children[0]}
|
|
144
|
+
<tbody>
|
|
145
|
+
{data && data.map(children[1].props.children)}
|
|
146
|
+
</tbody>
|
|
147
|
+
</Table>}
|
|
148
|
+
{ lastPage > 1 && <CardFooter>
|
|
149
|
+
<nav>
|
|
150
|
+
<BootstrapPagination
|
|
151
|
+
currentPage={page}
|
|
152
|
+
pageCount={lastPage}
|
|
153
|
+
onPageChange={index => setPage(index)}
|
|
135
154
|
/>
|
|
136
|
-
</
|
|
137
|
-
</
|
|
138
|
-
</
|
|
139
|
-
{data === null ? <Alert className="text-center mb-0 mx-3 " color="warning"><i className="fas fa-spinner fa-spin"></i></Alert> : !data.length ? <Alert className="text-center mx-3" color="danger">
|
|
140
|
-
<i className="far fa-times-circle"></i> <FormattedMessage id="NO_DATA_IS_AVAILABLE"/>
|
|
141
|
-
</Alert> : <Table hover bordered={bordered} striped={!noStrip} responsive size="md" className="mb-0 dataTable">
|
|
142
|
-
{children[0]}
|
|
143
|
-
<tbody>
|
|
144
|
-
{data && data.map(children[1].props.children)}
|
|
145
|
-
</tbody>
|
|
146
|
-
</Table>}
|
|
147
|
-
{ lastPage > 1 && <CardFooter>
|
|
148
|
-
<nav>
|
|
149
|
-
<BootstrapPagination
|
|
150
|
-
currentPage={page}
|
|
151
|
-
pageCount={lastPage}
|
|
152
|
-
onPageChange={index => setPage(index)}
|
|
153
|
-
/>
|
|
154
|
-
</nav>
|
|
155
|
-
</CardFooter> }
|
|
155
|
+
</nav>
|
|
156
|
+
</CardFooter> }
|
|
157
|
+
</RefreshScope>
|
|
156
158
|
</DataContextProvider>
|
|
157
159
|
</DataTableContext.Provider>
|
|
158
160
|
</Card>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
|
+
import { ValidatorOptionProvider } from "react-admin-base";
|
|
3
|
+
import { useIntl } from "react-intl";
|
|
4
|
+
import zxcvbn from 'zxcvbn';
|
|
5
|
+
|
|
6
|
+
export default function DefaultValidatorOptions({ children }) {
|
|
7
|
+
const intl = useIntl();
|
|
8
|
+
|
|
9
|
+
const options = useMemo(() => ({
|
|
10
|
+
validators: {
|
|
11
|
+
password: {
|
|
12
|
+
message: intl.formatMessage({ id: 'PASSWORD_NOMATCH' }),
|
|
13
|
+
rule: function (val, params) {
|
|
14
|
+
return val == params[0];
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
securepassword: {
|
|
18
|
+
message: intl.formatMessage({ id: 'INSECURE_PASSWORD' }),
|
|
19
|
+
rule: function (val, params) {
|
|
20
|
+
return !val || (zxcvbn(val, []).score >= 2);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}), [intl]);
|
|
25
|
+
|
|
26
|
+
return <ValidatorOptionProvider value={options}>
|
|
27
|
+
{ children }
|
|
28
|
+
</ValidatorOptionProvider>;
|
|
29
|
+
}
|
|
@@ -9,7 +9,7 @@ function ErrorHandler({ error }) {
|
|
|
9
9
|
</Alert>;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export default class ErrorBoundary extends React.Component {
|
|
12
|
+
export default class ErrorBoundary extends React.Component<{ children: React.ReactNode }> {
|
|
13
13
|
state = { hasError: false, error: null };
|
|
14
14
|
|
|
15
15
|
static getDerivedStateFromError(error) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
import React, { useContext,
|
|
3
|
-
import { useApp } from 'react-admin-base';
|
|
2
|
+
import React, { useContext, useMemo, useState } from 'react';
|
|
3
|
+
import { useApp, useLocalStorage } from 'react-admin-base';
|
|
4
4
|
import { IntlProvider } from 'react-intl';
|
|
5
5
|
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
|
|
6
6
|
|
|
@@ -20,23 +20,24 @@ export function useLanguage() {
|
|
|
20
20
|
return useContext(LanguageContext);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export default function LanguageProvider({ defaultLanguage, languages, children }) {
|
|
23
|
+
export default function LanguageProvider({ defaultLanguage, languages, loader, children }) {
|
|
24
24
|
const app = useApp();
|
|
25
|
+
|
|
26
|
+
const preferredLanguage = (navigator.languages && navigator.languages[0]) || navigator.language;
|
|
25
27
|
|
|
26
|
-
const
|
|
27
|
-
navigator.language;
|
|
28
|
-
|
|
29
|
-
const [ lang, setLang ] = useReducer((oldValue, newValue) => {
|
|
30
|
-
localStorage.setItem(app.id + "_" + 'language', newValue);
|
|
31
|
-
return newValue;
|
|
32
|
-
}, localStorage.getItem(app.id + "_" + 'language') || null);
|
|
28
|
+
const [ lang, setLang ] = useLocalStorage(app.id + "_language");
|
|
33
29
|
|
|
34
30
|
const activeLanguageKey = (!!lang && languages[lang] && lang) || (languages[preferredLanguage] && preferredLanguage) || (languages[defaultLanguage] && defaultLanguage);
|
|
35
31
|
const activeLanguage = languages[activeLanguageKey];
|
|
36
|
-
|
|
37
|
-
const messages = useMemo(() => ({ ...(_languages[activeLanguageKey] || _languages.en), ...activeLanguage.messages }), [activeLanguage])
|
|
38
32
|
const value = useMemo(() => [ activeLanguage, languages, setLang], [ activeLanguage, languages, setLang]);
|
|
39
33
|
|
|
34
|
+
const originalMessages = (loader && loader(activeLanguage)) || activeLanguage.messages;
|
|
35
|
+
|
|
36
|
+
const messages = useMemo(() => originalMessages && ({ ...(_languages[activeLanguageKey] || _languages.en), ...originalMessages }), [originalMessages, activeLanguage]);
|
|
37
|
+
|
|
38
|
+
if (!messages)
|
|
39
|
+
return null;
|
|
40
|
+
|
|
40
41
|
return <IntlProvider locale={activeLanguageKey} messages={messages}>
|
|
41
42
|
<LanguageContext.Provider value={value}>
|
|
42
43
|
{ children }
|
|
@@ -47,14 +48,17 @@ export default function LanguageProvider({ defaultLanguage, languages, children
|
|
|
47
48
|
export function LanguageSwitcher() {
|
|
48
49
|
const [show, setShow] = useState(false);
|
|
49
50
|
const [ activeLang, languages, setLanguage ] = useLanguage();
|
|
51
|
+
|
|
52
|
+
if (Object.keys(languages).length <= 1)
|
|
53
|
+
return null;
|
|
50
54
|
|
|
51
55
|
return <Dropdown isOpen={show} toggle={() => setShow(!show)}>
|
|
52
|
-
<DropdownToggle className="nav-flag
|
|
53
|
-
<img width="20" src={ activeLang.icon } alt={activeLang.name} />
|
|
56
|
+
<DropdownToggle className="nav-flag" nav caret>
|
|
57
|
+
{ activeLang.icon && <img width="20" className="me-1" src={ activeLang.icon } alt={activeLang.name} /> } {activeLang.name}
|
|
54
58
|
</DropdownToggle>
|
|
55
|
-
<DropdownMenu
|
|
59
|
+
<DropdownMenu>
|
|
56
60
|
{ Object.entries(languages).map(([key, value] : any) => <DropdownItem key={key} active={activeLang === value} onClick={() => setLanguage(key)}>
|
|
57
|
-
<img width="20" src={value.icon} alt={value.name} /> <span className="align-middle">{ value.name }</span>
|
|
61
|
+
{value.icon && <img width="20" className="me-1" src={value.icon} alt={value.name} /> } <span className="align-middle">{ value.name }</span>
|
|
58
62
|
</DropdownItem>) }
|
|
59
63
|
</DropdownMenu>
|
|
60
64
|
</Dropdown>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React, { useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { FormattedMessage, useIntl } from "react-intl";
|
|
3
|
+
import PasswordStrengthBar from "react-password-strength-bar";
|
|
4
|
+
import { FormGroup, Label, Input } from 'reactstrap';
|
|
5
|
+
import { Validator } from "./Validator";
|
|
6
|
+
|
|
7
|
+
interface BootstrapPasswordInput {
|
|
8
|
+
value?: string;
|
|
9
|
+
onChange: (str: string) => any;
|
|
10
|
+
className?: string;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
icon?: string;
|
|
13
|
+
required?: boolean;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function BootstrapPasswordInput({ className, value, onChange, disabled, placeholder }: BootstrapPasswordInput) {
|
|
18
|
+
const intl = useIntl();
|
|
19
|
+
|
|
20
|
+
const short = intl.formatMessage({ id: "PASSWORD_SHORT" });
|
|
21
|
+
const bad = intl.formatMessage({ id: "PASSWORD_BAD" });
|
|
22
|
+
const okay = intl.formatMessage({ id: "PASSWORD_OKAY" });
|
|
23
|
+
const good = intl.formatMessage({ id: "PASSWORD_GOOD" });
|
|
24
|
+
const perfect = intl.formatMessage({ id: "PASSWORD_PERFECT" });
|
|
25
|
+
|
|
26
|
+
const scoreWords = useMemo(() => [short, bad, okay, good, perfect], [short, bad, okay, good, perfect]);
|
|
27
|
+
|
|
28
|
+
return <>
|
|
29
|
+
<Input
|
|
30
|
+
className={className}
|
|
31
|
+
type="password"
|
|
32
|
+
value={value || ''}
|
|
33
|
+
onChange={a => onChange(a.currentTarget.value)}
|
|
34
|
+
disabled={disabled}
|
|
35
|
+
placeholder={placeholder}
|
|
36
|
+
/>
|
|
37
|
+
<PasswordStrengthBar
|
|
38
|
+
className="password-str-bar"
|
|
39
|
+
password={value || ''}
|
|
40
|
+
scoreWords={scoreWords}
|
|
41
|
+
shortScoreWord={short}
|
|
42
|
+
/>
|
|
43
|
+
</>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface PasswordInputParams {
|
|
47
|
+
value?: string;
|
|
48
|
+
onChange: (str: string) => any;
|
|
49
|
+
className?: string;
|
|
50
|
+
disabled?: boolean;
|
|
51
|
+
icon?: string;
|
|
52
|
+
required?: boolean;
|
|
53
|
+
placeholder?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default function PasswordInput({ value, onChange, className, disabled, icon, required, placeholder }: PasswordInputParams) {
|
|
57
|
+
const [ password2, setPassword2 ] = useState('');
|
|
58
|
+
|
|
59
|
+
const iconElem = icon && <i className={icon} />;
|
|
60
|
+
|
|
61
|
+
useEffect(function() {
|
|
62
|
+
if (!value) {
|
|
63
|
+
setPassword2('');
|
|
64
|
+
}
|
|
65
|
+
}, [value, setPassword2]);
|
|
66
|
+
|
|
67
|
+
return <>
|
|
68
|
+
<FormGroup className={className}>
|
|
69
|
+
{iconElem}
|
|
70
|
+
<Label><FormattedMessage id="PASSWORD" /></Label>
|
|
71
|
+
<Validator name="password" type={[required && "required", "securepassword"].filter(a => !!a)}>
|
|
72
|
+
<BootstrapPasswordInput
|
|
73
|
+
value={value}
|
|
74
|
+
onChange={onChange}
|
|
75
|
+
disabled={disabled}
|
|
76
|
+
placeholder={placeholder}
|
|
77
|
+
/>
|
|
78
|
+
</Validator>
|
|
79
|
+
</FormGroup>
|
|
80
|
+
{ !!(required || value) && <FormGroup className={className}>
|
|
81
|
+
{iconElem}
|
|
82
|
+
<Label><FormattedMessage id="PASSWORD_AGAIN" /></Label>
|
|
83
|
+
<Validator name="password2" type={[(required || value) && "required", { password: value || '' }].filter(a => !!a)}>
|
|
84
|
+
<Input
|
|
85
|
+
type="password"
|
|
86
|
+
value={password2 || ''}
|
|
87
|
+
onChange={a => setPassword2(a.currentTarget.value)}
|
|
88
|
+
disabled={disabled}
|
|
89
|
+
/>
|
|
90
|
+
</Validator>
|
|
91
|
+
</FormGroup> }
|
|
92
|
+
</>;
|
|
93
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { createContext, Dispatch, useContext, useEffect, useMemo, useReducer, useRef } from "react";
|
|
2
|
-
import { useApp } from "react-admin-base";
|
|
2
|
+
import { useApp, useLocalStorage } from "react-admin-base";
|
|
3
3
|
|
|
4
4
|
const ThemeContext = createContext(null as any);
|
|
5
5
|
const AllThemesContext = createContext(null as any);
|
|
@@ -12,19 +12,6 @@ export function useAllThemes() {
|
|
|
12
12
|
return useContext(AllThemesContext);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
function useLocalStorage(key: string) : [string, Dispatch<string>] {
|
|
16
|
-
const app = useApp();
|
|
17
|
-
|
|
18
|
-
const _key = app.id + '_' + key;
|
|
19
|
-
|
|
20
|
-
const previousValue = useMemo(() => localStorage.getItem(_key), [_key]);
|
|
21
|
-
|
|
22
|
-
return useReducer((_: string, newValue) => {
|
|
23
|
-
localStorage.setItem(_key, newValue);
|
|
24
|
-
return newValue;
|
|
25
|
-
}, previousValue);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
15
|
export default function ThemeProvider({ themes, defaultTheme, children }) {
|
|
29
16
|
const state = useLocalStorage('theme');
|
|
30
17
|
const [ theme, setTheme ] = state;
|
package/src/i18n/de.json
CHANGED
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
"USERNAME": "Benutzername",
|
|
5
5
|
"PASSWORD": "Passwort",
|
|
6
6
|
"FORGOT_PASSWORD": "Ich habe mein Passwort vergessen",
|
|
7
|
+
"INSECURE_PASSWORD": "Passwort ist nicht sicher",
|
|
8
|
+
"PASSWORD_NOMATCH": "Passwort ist falsch",
|
|
9
|
+
"PASSWORD_SHORT": "zu kurz",
|
|
10
|
+
"PASSWORD_BAD": "schlecht",
|
|
11
|
+
"PASSWORD_OKAY": "okay",
|
|
12
|
+
"PASSWORD_GOOD": "gut",
|
|
13
|
+
"PASSWORD_PERFECT": "perfekt",
|
|
7
14
|
"LOGIN": "Einloggen",
|
|
8
15
|
"LOGIN_HEAD": "Anmeldebereich",
|
|
9
16
|
"SUBMIT": "Absenden",
|
package/src/i18n/en.json
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
"ENTITY.CANCEL": "Cancel",
|
|
4
4
|
"USERNAME": "Username",
|
|
5
5
|
"PASSWORD": "Password",
|
|
6
|
+
"PASSWORD_AGAIN": "Password (again)",
|
|
7
|
+
"PASSWORD_SHORT": "too short",
|
|
8
|
+
"PASSWORD_BAD": "bad",
|
|
9
|
+
"PASSWORD_OKAY": "okay",
|
|
10
|
+
"PASSWORD_GOOD": "good",
|
|
11
|
+
"PASSWORD_PERFECT": "perfect",
|
|
12
|
+
"INSECURE_PASSWORD": "Password is not secure",
|
|
13
|
+
"PASSWORD_NOMATCH": "Passwords does not match",
|
|
6
14
|
"FORGOT_PASSWORD": "I forgot my password",
|
|
7
15
|
"LOGIN": "Login",
|
|
8
16
|
"LOGIN_HEAD": "Login Area",
|
|
@@ -12,7 +20,7 @@
|
|
|
12
20
|
"EMAIL": "Email",
|
|
13
21
|
"AUTH_CODE": "Authorization Code",
|
|
14
22
|
"ENTER_AUTH_CODE": "Please enter the verification code that we sent to {email}.",
|
|
15
|
-
"CHANGE_EMAIL": "Not your e-mail? <
|
|
23
|
+
"CHANGE_EMAIL": "Not your e-mail? <a>Sent to a new email address</a>.",
|
|
16
24
|
"PASSWORD_REPEAT": "Password (again)",
|
|
17
25
|
"VALIDATION.ERROR": "Entity has following errors:",
|
|
18
26
|
"ENTITY.SAVED": "Changes are saved.",
|
package/src/i18n/tr.json
CHANGED
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
"USERNAME": "Kullanıcı Adı",
|
|
5
5
|
"PASSWORD": "Şifre",
|
|
6
6
|
"FORGOT_PASSWORD": "Şifremi unuttum",
|
|
7
|
+
"INSECURE_PASSWORD": "Şifre güvenli değil",
|
|
8
|
+
"PASSWORD_NOMATCH": "Şifreler uyuşmuyor",
|
|
9
|
+
"PASSWORD_SHORT": "çok kısa",
|
|
10
|
+
"PASSWORD_BAD": "kötü",
|
|
11
|
+
"PASSWORD_OKAY": "idare eder",
|
|
12
|
+
"PASSWORD_GOOD": "iyi",
|
|
13
|
+
"PASSWORD_PERFECT": "harika",
|
|
7
14
|
"SUBMIT": "Gönder",
|
|
8
15
|
"LOGIN": "Giriş",
|
|
9
16
|
"LOGIN_HEAD": "Oturum Açma Alanı",
|
package/src/index.ts
CHANGED
|
@@ -19,10 +19,14 @@ import { useMenuState, useIsMobile } from './Components/MenuState';
|
|
|
19
19
|
import TopProgressBar from './Components/TopProgressBar';
|
|
20
20
|
import ThemeProvider, { useTheme, useAllThemes } from './Components/ThemeProvider';
|
|
21
21
|
import StepList, { StepItem } from './Components/StepList';
|
|
22
|
+
import PasswordInput from './Components/PasswordInput';
|
|
23
|
+
import DefaultValidatorOptions from './Components/DefaultValidatorOptions';
|
|
22
24
|
|
|
23
25
|
export {
|
|
24
26
|
ThemeProvider, useTheme, useAllThemes,
|
|
25
27
|
useIsMobile, useMenuState,
|
|
28
|
+
DefaultValidatorOptions,
|
|
29
|
+
PasswordInput,
|
|
26
30
|
StepList, StepItem,
|
|
27
31
|
TopProgressBar,
|
|
28
32
|
CRUD, ModalEntityEditor, CRUDActions,
|