react-admin-base-bootstrap 0.7.5 → 0.7.8
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 +2 -5
- 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/PasswordInput.d.ts +11 -0
- package/lib/esm/Components/PasswordInput.js +39 -0
- package/lib/esm/Components/RichTextEditor.d.ts +4 -0
- package/lib/esm/Components/RichTextEditor.js +52 -0
- 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 +5 -4
- package/src/Components/DefaultValidatorOptions.tsx +29 -0
- package/src/Components/ErrorBoundary.tsx +1 -1
- package/src/Components/PasswordInput.tsx +95 -0
- 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
|
@@ -67,10 +67,7 @@ export function ActionsColumn() {
|
|
|
67
67
|
export function Column(props) {
|
|
68
68
|
const [params, setParams] = useContext(DataTableContext);
|
|
69
69
|
const { sort } = props;
|
|
70
|
-
return React.createElement("th", Object.assign({}, props, { style: props.sort && { cursor: 'pointer' }, onClick: props.sort && (() => setParams({
|
|
71
|
-
sort: sort,
|
|
72
|
-
desc: params.sort === sort ? !params.desc : true
|
|
73
|
-
})) }),
|
|
70
|
+
return React.createElement("th", Object.assign({}, props, { style: props.sort && { cursor: 'pointer' }, onClick: props.sort && (() => setParams(params => (Object.assign(Object.assign({}, params), { sort: sort, desc: params.sort === sort ? !params.desc : true })))) }),
|
|
74
71
|
props.children,
|
|
75
72
|
" ",
|
|
76
73
|
sort && params.sort && params.sort === sort ? params.desc ?
|
|
@@ -87,7 +84,7 @@ export default function BootstrapTable({ url, bordered, noStrip, defaultParams,
|
|
|
87
84
|
useEffect(function () {
|
|
88
85
|
if (ref.current !== defaultParams) {
|
|
89
86
|
ref.current = defaultParams;
|
|
90
|
-
setParams(defaultParams);
|
|
87
|
+
setParams(params => (Object.assign(Object.assign({}, params), defaultParams)));
|
|
91
88
|
}
|
|
92
89
|
}, [defaultParams, ref, setParams]);
|
|
93
90
|
useEffect(function () {
|
|
@@ -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
|
}
|
|
@@ -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, autoComplete: "new-password" }),
|
|
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, autoComplete: "new-password" }))));
|
|
39
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { LexicalComposer } from "@lexical/react/LexicalComposer";
|
|
3
|
+
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
|
|
4
|
+
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
|
|
5
|
+
import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
|
|
6
|
+
import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin";
|
|
7
|
+
import { HeadingNode, QuoteNode } from "@lexical/rich-text";
|
|
8
|
+
import { TableCellNode, TableNode, TableRowNode } from "@lexical/table";
|
|
9
|
+
import { ListItemNode, ListNode } from "@lexical/list";
|
|
10
|
+
import { CodeHighlightNode, CodeNode } from "@lexical/code";
|
|
11
|
+
import { AutoLinkNode, LinkNode } from "@lexical/link";
|
|
12
|
+
import { LinkPlugin } from "@lexical/react/LexicalLinkPlugin";
|
|
13
|
+
import { ListPlugin } from "@lexical/react/LexicalListPlugin";
|
|
14
|
+
import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin";
|
|
15
|
+
import { TRANSFORMERS } from "@lexical/markdown";
|
|
16
|
+
import ToolbarPlugin from '../Lexical/ToolbarPlugin';
|
|
17
|
+
function Placeholder() {
|
|
18
|
+
return React.createElement("div", { className: "editor-placeholder" }, "Enter some rich text...");
|
|
19
|
+
}
|
|
20
|
+
const editorConfig = {
|
|
21
|
+
namespace: '',
|
|
22
|
+
// Handling of errors during update
|
|
23
|
+
onError(error) {
|
|
24
|
+
throw error;
|
|
25
|
+
},
|
|
26
|
+
// Any custom nodes go here
|
|
27
|
+
nodes: [
|
|
28
|
+
HeadingNode,
|
|
29
|
+
ListNode,
|
|
30
|
+
ListItemNode,
|
|
31
|
+
QuoteNode,
|
|
32
|
+
CodeNode,
|
|
33
|
+
CodeHighlightNode,
|
|
34
|
+
TableNode,
|
|
35
|
+
TableCellNode,
|
|
36
|
+
TableRowNode,
|
|
37
|
+
AutoLinkNode,
|
|
38
|
+
LinkNode
|
|
39
|
+
]
|
|
40
|
+
};
|
|
41
|
+
export default function RichTextEditor({ value, onChange }) {
|
|
42
|
+
return React.createElement(LexicalComposer, { initialConfig: editorConfig },
|
|
43
|
+
React.createElement("div", { className: "editor-container" },
|
|
44
|
+
React.createElement(ToolbarPlugin, null),
|
|
45
|
+
React.createElement("div", { className: "editor-inner" },
|
|
46
|
+
React.createElement(RichTextPlugin, { contentEditable: React.createElement(ContentEditable, { className: "editor-input" }), placeholder: React.createElement(Placeholder, null) }),
|
|
47
|
+
React.createElement(HistoryPlugin, null),
|
|
48
|
+
React.createElement(AutoFocusPlugin, null),
|
|
49
|
+
React.createElement(ListPlugin, null),
|
|
50
|
+
React.createElement(LinkPlugin, null),
|
|
51
|
+
React.createElement(MarkdownShortcutPlugin, { transformers: TRANSFORMERS }))));
|
|
52
|
+
}
|
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.8",
|
|
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
|
}
|
|
@@ -64,10 +64,11 @@ export function Column(props) {
|
|
|
64
64
|
return <th
|
|
65
65
|
{...props}
|
|
66
66
|
style={props.sort && {cursor: 'pointer'}}
|
|
67
|
-
onClick={props.sort && (() => setParams({
|
|
68
|
-
|
|
67
|
+
onClick={props.sort && (() => setParams(params => ({
|
|
68
|
+
...params,
|
|
69
|
+
sort: sort,
|
|
69
70
|
desc: params.sort === sort ? !params.desc : true
|
|
70
|
-
}))}
|
|
71
|
+
})))}
|
|
71
72
|
>{props.children} {sort && params.sort && params.sort === sort ? params.desc ?
|
|
72
73
|
<i className="fa fa-sort-down"/> :
|
|
73
74
|
<i className="fa fa-sort-up"/> : ''}
|
|
@@ -85,7 +86,7 @@ export default function BootstrapTable({url, bordered, noStrip, defaultParams, a
|
|
|
85
86
|
useEffect(function () {
|
|
86
87
|
if (ref.current !== defaultParams) {
|
|
87
88
|
ref.current = defaultParams;
|
|
88
|
-
setParams(defaultParams);
|
|
89
|
+
setParams(params => ({ ...params, ...defaultParams }));
|
|
89
90
|
}
|
|
90
91
|
}, [defaultParams, ref, setParams]);
|
|
91
92
|
|
|
@@ -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) {
|
|
@@ -0,0 +1,95 @@
|
|
|
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
|
+
autoComplete="new-password"
|
|
37
|
+
/>
|
|
38
|
+
<PasswordStrengthBar
|
|
39
|
+
className="password-str-bar"
|
|
40
|
+
password={value || ''}
|
|
41
|
+
scoreWords={scoreWords}
|
|
42
|
+
shortScoreWord={short}
|
|
43
|
+
/>
|
|
44
|
+
</>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface PasswordInputParams {
|
|
48
|
+
value?: string;
|
|
49
|
+
onChange: (str: string) => any;
|
|
50
|
+
className?: string;
|
|
51
|
+
disabled?: boolean;
|
|
52
|
+
icon?: string;
|
|
53
|
+
required?: boolean;
|
|
54
|
+
placeholder?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default function PasswordInput({ value, onChange, className, disabled, icon, required, placeholder }: PasswordInputParams) {
|
|
58
|
+
const [ password2, setPassword2 ] = useState('');
|
|
59
|
+
|
|
60
|
+
const iconElem = icon && <i className={icon} />;
|
|
61
|
+
|
|
62
|
+
useEffect(function() {
|
|
63
|
+
if (!value) {
|
|
64
|
+
setPassword2('');
|
|
65
|
+
}
|
|
66
|
+
}, [value, setPassword2]);
|
|
67
|
+
|
|
68
|
+
return <>
|
|
69
|
+
<FormGroup className={className}>
|
|
70
|
+
{iconElem}
|
|
71
|
+
<Label><FormattedMessage id="PASSWORD" /></Label>
|
|
72
|
+
<Validator name="password" type={[required && "required", "securepassword"].filter(a => !!a)}>
|
|
73
|
+
<BootstrapPasswordInput
|
|
74
|
+
value={value}
|
|
75
|
+
onChange={onChange}
|
|
76
|
+
disabled={disabled}
|
|
77
|
+
placeholder={placeholder}
|
|
78
|
+
/>
|
|
79
|
+
</Validator>
|
|
80
|
+
</FormGroup>
|
|
81
|
+
{ !!(required || value) && <FormGroup className={className}>
|
|
82
|
+
{iconElem}
|
|
83
|
+
<Label><FormattedMessage id="PASSWORD_AGAIN" /></Label>
|
|
84
|
+
<Validator name="password2" type={[(required || value) && "required", { password: value || '' }].filter(a => !!a)}>
|
|
85
|
+
<Input
|
|
86
|
+
type="password"
|
|
87
|
+
value={password2 || ''}
|
|
88
|
+
onChange={a => setPassword2(a.currentTarget.value)}
|
|
89
|
+
disabled={disabled}
|
|
90
|
+
autoComplete="new-password"
|
|
91
|
+
/>
|
|
92
|
+
</Validator>
|
|
93
|
+
</FormGroup> }
|
|
94
|
+
</>;
|
|
95
|
+
}
|
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,
|