react-admin-base-bootstrap 0.7.8 → 0.8.1
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/lib/esm/Components/ApiSelect.d.ts +19 -1
- package/lib/esm/Components/ApiSelect.js +3 -1
- package/lib/esm/Components/BootstrapDataTable.d.ts +24 -7
- package/lib/esm/Components/BootstrapDataTable.js +37 -29
- package/lib/esm/Components/CRUD.d.ts +7 -1
- package/lib/esm/Components/CRUD.js +2 -2
- package/lib/esm/Components/CheckBox.d.ts +10 -1
- package/lib/esm/Components/CheckBox.js +1 -1
- package/lib/esm/Components/DefaultValidatorOptions.d.ts +6 -3
- package/lib/esm/Components/ExternalLoginButton.d.ts +8 -6
- package/lib/esm/Components/FilePickerCore.d.ts +5 -3
- package/lib/esm/Components/FilePickerCore.js +4 -4
- package/lib/esm/Components/ImagePicker.d.ts +9 -1
- package/lib/esm/Components/LanguageProvider.d.ts +8 -5
- package/lib/esm/Components/LoadingButton.d.ts +2 -1
- package/lib/esm/Components/MenuState.d.ts +1 -1
- package/lib/esm/Components/SingleFilePicker.d.ts +2 -3
- package/lib/esm/Components/StepList.d.ts +14 -2
- package/lib/esm/Components/TopProgressBar.d.ts +6 -3
- package/lib/esm/Components/Validator.d.ts +1 -1
- package/lib/esm/index.d.ts +2 -2
- package/lib/esm/index.js +2 -2
- package/package.json +13 -13
- package/src/Components/ApiSelect.tsx +31 -11
- package/src/Components/BootstrapDataTable.tsx +80 -44
- package/src/Components/CRUD.tsx +10 -4
- package/src/Components/CheckBox.tsx +10 -3
- package/src/Components/DefaultValidatorOptions.tsx +5 -1
- package/src/Components/ExcelExportButton.tsx +5 -3
- package/src/Components/ExternalLoginButton.tsx +8 -1
- package/src/Components/FilePickerCore.tsx +9 -5
- package/src/Components/ImagePicker.tsx +4 -4
- package/src/Components/LanguageProvider.tsx +8 -1
- package/src/Components/LoadingButton.tsx +2 -2
- package/src/Components/SingleFilePicker.tsx +4 -4
- package/src/Components/StepList.tsx +14 -2
- package/src/Components/TopProgressBar.tsx +6 -2
- package/src/Components/Validator.tsx +5 -5
- package/src/index.ts +2 -1
|
@@ -1,3 +1,21 @@
|
|
|
1
1
|
/** @jsx jsx */
|
|
2
2
|
import { jsx } from '@emotion/react';
|
|
3
|
-
|
|
3
|
+
import React from 'react';
|
|
4
|
+
export interface ApiSelectProps<Option = any> {
|
|
5
|
+
url?: string;
|
|
6
|
+
value: Option | Option[];
|
|
7
|
+
onChange: (a: Option | Option[] | null) => void;
|
|
8
|
+
getOptionLabel?: (a: any) => string;
|
|
9
|
+
getOptionValue?: (a: any) => string;
|
|
10
|
+
onCreateOption?: (a: string) => Option | Promise<Option>;
|
|
11
|
+
filter?: (a: Option) => boolean;
|
|
12
|
+
group?: (a: Option[]) => any[];
|
|
13
|
+
isMulti?: boolean;
|
|
14
|
+
idKey?: string;
|
|
15
|
+
nameKey?: string;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
placeholder?: string;
|
|
18
|
+
staticOptions?: any[];
|
|
19
|
+
getNewOptionData?: (name: string, elem: React.ReactNode) => any | null;
|
|
20
|
+
}
|
|
21
|
+
export default function ApiSelect<Option = any>(props: ApiSelectProps<Option>): jsx.JSX.Element;
|
|
@@ -55,6 +55,8 @@ export default function ApiSelect(props) {
|
|
|
55
55
|
}
|
|
56
56
|
const handleCreateOption = useCallback(function (input) {
|
|
57
57
|
return __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
if (!onCreateOption)
|
|
59
|
+
return null;
|
|
58
60
|
setCreating(true);
|
|
59
61
|
try {
|
|
60
62
|
let option = yield onCreateOption(input);
|
|
@@ -78,5 +80,5 @@ export default function ApiSelect(props) {
|
|
|
78
80
|
setIsMenuOpen(false);
|
|
79
81
|
}, [setIsMenuOpen]);
|
|
80
82
|
const Component = onCreateOption ? CreatableSelect : Select;
|
|
81
|
-
return jsx(Component, Object.assign({}, props, { className: 'react-select-container', classNamePrefix: "react-select", onCreateOption:
|
|
83
|
+
return jsx(Component, Object.assign({}, props, { className: 'react-select-container', classNamePrefix: "react-select", onCreateOption: onCreateOption && handleCreateOption, getNewOptionData: (onCreateOption && (getNewOptionData || ((inputValue) => ({ [nameKey || 'name']: inputValue, __isNew__: true })))) || undefined, inputValue: search, onInputChange: a => setSearch(a), components: Components, isLoading: !!loading || creating, getOptionLabel: getOptionLabel || ((row) => row[nameKey || 'name']), getOptionValue: getOptionValue || ((row) => row[idKey || 'id']), isDisabled: !!disabled || creating, isClearable: true, isSearchable: true, placeholder: placeholder || intl.formatMessage({ id: 'SELECT' }), options: !options ? [] : ((filter && options.filter(filter)) || options), onMenuOpen: onMenuOpen, onMenuClose: onMenuClose }));
|
|
82
84
|
}
|
|
@@ -1,11 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
export declare function useDataTableContext(): any;
|
|
2
|
-
|
|
3
|
-
edit
|
|
4
|
-
del
|
|
5
|
-
rowSpan?:
|
|
6
|
-
children?:
|
|
7
|
-
}
|
|
3
|
+
declare type ActionsProp = {
|
|
4
|
+
edit?: string;
|
|
5
|
+
del?: string;
|
|
6
|
+
rowSpan?: number | undefined;
|
|
7
|
+
children?: React.ReactNode;
|
|
8
|
+
};
|
|
9
|
+
export declare function Actions({ edit, del, rowSpan, children }: ActionsProp): JSX.Element;
|
|
8
10
|
export declare function IdColumn(): JSX.Element;
|
|
9
11
|
export declare function ActionsColumn(): JSX.Element;
|
|
10
12
|
export declare function Column(props: any): JSX.Element;
|
|
11
|
-
export
|
|
13
|
+
export interface BootstrapTableProps {
|
|
14
|
+
url: string;
|
|
15
|
+
bordered?: boolean;
|
|
16
|
+
noStrip?: boolean;
|
|
17
|
+
defaultParams?: any;
|
|
18
|
+
body?: any;
|
|
19
|
+
add?: string;
|
|
20
|
+
children: any;
|
|
21
|
+
innerRef?: any;
|
|
22
|
+
}
|
|
23
|
+
interface RowRendererProps<Row = any> {
|
|
24
|
+
render: (row: Row) => React.ReactNode;
|
|
25
|
+
}
|
|
26
|
+
export declare function RowRenderer<Row = any>({ render }: RowRendererProps<Row>): JSX.Element;
|
|
27
|
+
export default function BootstrapTable({ url, bordered, noStrip, defaultParams, add, children, innerRef, body }: BootstrapTableProps): JSX.Element;
|
|
28
|
+
export {};
|
|
@@ -15,6 +15,8 @@ import { Alert, Button, Card, CardFooter, CardHeader, Col, Input, Row, Table } f
|
|
|
15
15
|
import Swal from 'sweetalert2';
|
|
16
16
|
import BootstrapPagination from "./BootstrapPagination";
|
|
17
17
|
const DataTableContext = React.createContext(null);
|
|
18
|
+
const RowDatasContext = React.createContext(null);
|
|
19
|
+
const RowDataContext = React.createContext(null);
|
|
18
20
|
export function useDataTableContext() {
|
|
19
21
|
return useContext(DataTableContext);
|
|
20
22
|
}
|
|
@@ -74,13 +76,18 @@ export function Column(props) {
|
|
|
74
76
|
React.createElement("i", { className: "fa fa-sort-down" }) :
|
|
75
77
|
React.createElement("i", { className: "fa fa-sort-up" }) : '');
|
|
76
78
|
}
|
|
79
|
+
export function RowRenderer({ render }) {
|
|
80
|
+
const rows = useContext(RowDatasContext);
|
|
81
|
+
return React.createElement("tbody", null, rows.map(render));
|
|
82
|
+
}
|
|
77
83
|
export default function BootstrapTable({ url, bordered, noStrip, defaultParams, add, children, innerRef, body }) {
|
|
78
|
-
|
|
84
|
+
const state = useState(Object.assign({ sort: 'id' }, defaultParams));
|
|
79
85
|
const [params, setParams] = state;
|
|
80
86
|
const [page, lastPage, setPage, data, itemPerPage, setItemPerPage, update] = useDataTable(url, params, body);
|
|
81
87
|
const intl = useIntl();
|
|
82
88
|
const [api] = useAuth();
|
|
83
|
-
|
|
89
|
+
console.log(children[1]);
|
|
90
|
+
const ref = useRef(defaultParams);
|
|
84
91
|
useEffect(function () {
|
|
85
92
|
if (ref.current !== defaultParams) {
|
|
86
93
|
ref.current = defaultParams;
|
|
@@ -109,31 +116,32 @@ export default function BootstrapTable({ url, bordered, noStrip, defaultParams,
|
|
|
109
116
|
React.createElement(DataTableContext.Provider, { value: state },
|
|
110
117
|
React.createElement(DataContextProvider, { value: fetchData },
|
|
111
118
|
React.createElement(RefreshScope, { update: update },
|
|
112
|
-
React.createElement(
|
|
113
|
-
React.createElement(
|
|
114
|
-
|
|
115
|
-
React.createElement(
|
|
116
|
-
React.createElement(
|
|
117
|
-
|
|
118
|
-
React.createElement(
|
|
119
|
-
React.createElement(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
React.createElement(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
React.createElement(
|
|
138
|
-
React.createElement(
|
|
119
|
+
React.createElement(RowDatasContext.Provider, { value: data },
|
|
120
|
+
React.createElement(CardHeader, null,
|
|
121
|
+
React.createElement(Row, null,
|
|
122
|
+
add && React.createElement(Col, { xs: "12", md: "2" },
|
|
123
|
+
React.createElement(Link, { to: add, className: "btn btn-primary font-xl d-block" },
|
|
124
|
+
React.createElement("i", { className: "fa fa-plus" }))),
|
|
125
|
+
React.createElement(Col, { md: "2" },
|
|
126
|
+
React.createElement(Input, { type: "select", value: itemPerPage.toString(), onChange: a => setItemPerPage(+a.currentTarget.value) },
|
|
127
|
+
React.createElement("option", { value: "1" }, "1"),
|
|
128
|
+
React.createElement("option", { value: "20" }, "20"),
|
|
129
|
+
React.createElement("option", { value: "50" }, "50"),
|
|
130
|
+
React.createElement("option", { value: "100" }, "100"),
|
|
131
|
+
React.createElement("option", { value: "150" }, "150"),
|
|
132
|
+
React.createElement("option", { value: "200" }, "200"),
|
|
133
|
+
React.createElement("option", { value: "-1" }, intl.formatMessage({ id: "ALL" })))),
|
|
134
|
+
children[2],
|
|
135
|
+
React.createElement(Col, { md: "3", className: "ms-auto" },
|
|
136
|
+
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 })) })))),
|
|
137
|
+
data === null ? React.createElement(Alert, { className: "text-center mb-0 mx-3 ", color: "warning" },
|
|
138
|
+
React.createElement("i", { className: "fas fa-spinner fa-spin" })) : !data.length ? React.createElement(Alert, { className: "text-center mx-3", color: "danger" },
|
|
139
|
+
React.createElement("i", { className: "far fa-times-circle" }),
|
|
140
|
+
" ",
|
|
141
|
+
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" },
|
|
142
|
+
children[0],
|
|
143
|
+
children[1].type === "tbody" ? React.createElement("tbody", null, data && data.map(children[1].props.children)) : children[1]),
|
|
144
|
+
lastPage > 1 && React.createElement(CardFooter, null,
|
|
145
|
+
React.createElement("nav", null,
|
|
146
|
+
React.createElement(BootstrapPagination, { currentPage: page, pageCount: lastPage, onPageChange: index => setPage(index) }))))))));
|
|
139
147
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { BootstrapTableProps } from './BootstrapDataTable';
|
|
2
3
|
declare type ModalEntityEditorParams = {
|
|
3
4
|
entity: any;
|
|
4
5
|
title?: string;
|
|
@@ -16,5 +17,10 @@ declare type CrudActionProps = {
|
|
|
16
17
|
children?: React.ReactNode;
|
|
17
18
|
};
|
|
18
19
|
export declare function CRUDActions({ id, edit, del, children }: CrudActionProps): JSX.Element;
|
|
19
|
-
|
|
20
|
+
interface CRUDProps extends BootstrapTableProps {
|
|
21
|
+
apiUrl?: string;
|
|
22
|
+
Component: any;
|
|
23
|
+
noAdd?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export default function CRUD(props: CRUDProps): JSX.Element;
|
|
20
26
|
export {};
|
|
@@ -92,7 +92,7 @@ function ComponentWrapper(_a) {
|
|
|
92
92
|
export default function CRUD(props) {
|
|
93
93
|
const ref = useRef(null);
|
|
94
94
|
const { url, apiUrl, Component, defaultParams, noAdd } = props;
|
|
95
|
-
|
|
95
|
+
const reload = useCallback(function () {
|
|
96
96
|
return __awaiter(this, void 0, void 0, function* () {
|
|
97
97
|
if (ref.current) {
|
|
98
98
|
ref.current({});
|
|
@@ -103,5 +103,5 @@ export default function CRUD(props) {
|
|
|
103
103
|
React.createElement(Routes, null,
|
|
104
104
|
!noAdd && React.createElement(Route, { path: "create", element: React.createElement(ComponentWrapper, Object.assign({ Component: Component, url: url, onReload: reload }, (defaultParams || {}))) }),
|
|
105
105
|
React.createElement(Route, { path: ":id/edit", element: React.createElement(ComponentWrapper, Object.assign({ Component: Component, url: url, onReload: reload }, (defaultParams || {}))) })),
|
|
106
|
-
React.createElement(BootstrapDataTable, Object.assign({ innerRef: ref, add: !noAdd && "create" }, props, { url: apiUrl || url })));
|
|
106
|
+
React.createElement(BootstrapDataTable, Object.assign({ innerRef: ref, add: (!noAdd && "create") || undefined }, props, { url: apiUrl || url })));
|
|
107
107
|
}
|
|
@@ -1 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { InputProps } from "reactstrap";
|
|
3
|
+
interface CheckBoxProps extends InputProps {
|
|
4
|
+
id: string;
|
|
5
|
+
type?: "checkbox" | "radio";
|
|
6
|
+
label?: React.ReactNode;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export default function CheckBox(props: CheckBoxProps): JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -2,6 +2,6 @@ import React from "react";
|
|
|
2
2
|
import { FormGroup, Input, Label } from "reactstrap";
|
|
3
3
|
export default function CheckBox(props) {
|
|
4
4
|
return React.createElement(FormGroup, { check: true },
|
|
5
|
-
React.createElement(Input, Object.assign({ type: props.type || "checkbox" }, props, { label: undefined })),
|
|
5
|
+
React.createElement(Input, Object.assign({ type: props.type || "checkbox" }, props, { children: undefined, label: undefined })),
|
|
6
6
|
React.createElement(Label, { check: true, for: props.id }, props.children || props.label));
|
|
7
7
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import React from "react";
|
|
2
|
+
declare type DefaultValidatorOptionsProps = {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
};
|
|
5
|
+
export default function DefaultValidatorOptions({ children }: DefaultValidatorOptionsProps): JSX.Element;
|
|
6
|
+
export {};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
id:
|
|
3
|
-
icon
|
|
4
|
-
name:
|
|
5
|
-
url:
|
|
6
|
-
}
|
|
1
|
+
declare type ExternalLoginButtonProps = {
|
|
2
|
+
id: string;
|
|
3
|
+
icon?: string;
|
|
4
|
+
name: string;
|
|
5
|
+
url: string;
|
|
6
|
+
};
|
|
7
|
+
export default function ExternalLoginButton({ id, icon, name, url }: ExternalLoginButtonProps): JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
children:
|
|
4
|
-
}
|
|
2
|
+
declare type RelativeProps = {
|
|
3
|
+
children: JSX.Element;
|
|
4
|
+
};
|
|
5
|
+
export declare function Relative({ children }: RelativeProps): React.FunctionComponentElement<any> | null;
|
|
5
6
|
export declare function Preview({ value }: {
|
|
6
7
|
value: any;
|
|
7
8
|
}): JSX.Element | null;
|
|
@@ -14,3 +15,4 @@ export default function FilePickerCore({ disabled, className, accepts, value, on
|
|
|
14
15
|
children?: any;
|
|
15
16
|
transform?: any;
|
|
16
17
|
}): JSX.Element | null;
|
|
18
|
+
export {};
|
|
@@ -3,14 +3,14 @@ import prettysize from 'prettysize';
|
|
|
3
3
|
import { Button } from "reactstrap";
|
|
4
4
|
import { useApp, useFilePicker, usePreviewComponent } from "react-admin-base";
|
|
5
5
|
import { FormattedMessage } from "react-intl";
|
|
6
|
-
|
|
6
|
+
const photo_ext = ["png", "jpg", "jpeg", "svg"];
|
|
7
7
|
function is_photo(name) {
|
|
8
8
|
return photo_ext.indexOf(name.split('.')[1]) !== -1;
|
|
9
9
|
}
|
|
10
10
|
function is_absolute(url) {
|
|
11
11
|
if (url.indexOf("blob:") === 0)
|
|
12
12
|
return false;
|
|
13
|
-
|
|
13
|
+
const pat = /^https?:\/\//i;
|
|
14
14
|
return !pat.test(url);
|
|
15
15
|
}
|
|
16
16
|
export function Relative({ children }) {
|
|
@@ -24,8 +24,8 @@ export function Relative({ children }) {
|
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
export function Preview({ value }) {
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const name = value.$name;
|
|
28
|
+
const src = value.$blob_url || value.$src;
|
|
29
29
|
if (is_photo(name)) {
|
|
30
30
|
return React.createElement("div", { className: "mt-2" },
|
|
31
31
|
React.createElement(Relative, null,
|
|
@@ -1 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { SingleFilePickerProps } from './SingleFilePicker';
|
|
2
|
+
interface ImagePickerProps extends SingleFilePickerProps {
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
type: string;
|
|
6
|
+
exact?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export default function ImagePicker(props: ImagePickerProps): JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
export declare function useLanguage(): any;
|
|
2
|
-
|
|
3
|
-
defaultLanguage:
|
|
3
|
+
declare type LanguageProviderProps = {
|
|
4
|
+
defaultLanguage: string;
|
|
4
5
|
languages: any;
|
|
5
|
-
loader: any;
|
|
6
|
-
children:
|
|
7
|
-
}
|
|
6
|
+
loader?: (language: any) => any;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
};
|
|
9
|
+
export default function LanguageProvider({ defaultLanguage, languages, loader, children }: LanguageProviderProps): JSX.Element | null;
|
|
8
10
|
export declare function LanguageSwitcher(): JSX.Element | null;
|
|
11
|
+
export {};
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { ButtonProps } from 'reactstrap';
|
|
2
|
+
export default function LoadingButton(props: ButtonProps): JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
2
|
+
export interface SingleFilePickerProps {
|
|
3
3
|
disabled?: boolean;
|
|
4
4
|
className?: string;
|
|
5
5
|
accepts?: string;
|
|
@@ -7,6 +7,5 @@ declare type SingleFilePickerProps = {
|
|
|
7
7
|
onChange: (value: any) => void;
|
|
8
8
|
children?: (value: any) => React.ReactNode;
|
|
9
9
|
transform?: any;
|
|
10
|
-
}
|
|
10
|
+
}
|
|
11
11
|
export default function SingleFilePicker({ disabled, className, accepts, value, onChange, transform, children }: SingleFilePickerProps): JSX.Element;
|
|
12
|
-
export {};
|
|
@@ -1,2 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import React from "react";
|
|
2
|
+
declare type StepListProps = {
|
|
3
|
+
active: number;
|
|
4
|
+
setActive: (active: number) => {};
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
};
|
|
7
|
+
export default function StepList({ active, setActive, children }: StepListProps): JSX.Element;
|
|
8
|
+
declare type StepItemProps = {
|
|
9
|
+
title?: string;
|
|
10
|
+
translate?: string;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare function StepItem({ title, translate, disabled }: StepItemProps): JSX.Element;
|
|
14
|
+
export {};
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
declare type TopProgressBarProps = {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
};
|
|
5
|
+
export default function TopProgressBar({ children }: TopProgressBarProps): React.ReactNode;
|
|
6
|
+
export {};
|
package/lib/esm/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import BootstrapTable, { Actions, ActionsColumn, Column, default as BootstrapDataTable, IdColumn, useDataTableContext } from './Components/BootstrapDataTable';
|
|
1
|
+
import BootstrapTable, { RowRenderer, Actions, ActionsColumn, Column, default as BootstrapDataTable, IdColumn, useDataTableContext } from './Components/BootstrapDataTable';
|
|
2
2
|
import CRUD, { CRUDActions, ModalEntityEditor } from './Components/CRUD';
|
|
3
3
|
import EntityEditor from "./Components/EntityEditor";
|
|
4
4
|
import ExcelExportButton from './Components/ExcelExportButton';
|
|
@@ -20,4 +20,4 @@ import ThemeProvider, { useTheme, useAllThemes } from './Components/ThemeProvide
|
|
|
20
20
|
import StepList, { StepItem } from './Components/StepList';
|
|
21
21
|
import PasswordInput from './Components/PasswordInput';
|
|
22
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 };
|
|
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, RowRenderer, LanguageProvider, useLanguage, LanguageSwitcher, ErrorBoundary, CheckBox };
|
package/lib/esm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import BootstrapTable, { Actions, ActionsColumn, Column, default as BootstrapDataTable, IdColumn, useDataTableContext } from './Components/BootstrapDataTable';
|
|
1
|
+
import BootstrapTable, { RowRenderer, Actions, ActionsColumn, Column, default as BootstrapDataTable, IdColumn, useDataTableContext } from './Components/BootstrapDataTable';
|
|
2
2
|
import CRUD, { CRUDActions, ModalEntityEditor } from './Components/CRUD';
|
|
3
3
|
import EntityEditor from "./Components/EntityEditor";
|
|
4
4
|
import ExcelExportButton from './Components/ExcelExportButton';
|
|
@@ -20,4 +20,4 @@ import ThemeProvider, { useTheme, useAllThemes } from './Components/ThemeProvide
|
|
|
20
20
|
import StepList, { StepItem } from './Components/StepList';
|
|
21
21
|
import PasswordInput from './Components/PasswordInput';
|
|
22
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 };
|
|
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, RowRenderer, 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.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
@@ -28,29 +28,29 @@
|
|
|
28
28
|
"react": "^18.2.0",
|
|
29
29
|
"react-dom": "^18.2.0",
|
|
30
30
|
"react-intl": "^5.21.0",
|
|
31
|
-
"react-router-dom": "^6.
|
|
31
|
+
"react-router-dom": "^6.4.2"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@emotion/react": "^11.
|
|
35
|
-
"@fortawesome/fontawesome-free": "^6.
|
|
36
|
-
"bootstrap": "^5.
|
|
34
|
+
"@emotion/react": "^11.10.4",
|
|
35
|
+
"@fortawesome/fontawesome-free": "^6.2.0",
|
|
36
|
+
"bootstrap": "^5.2.2",
|
|
37
37
|
"file-dialog": "^0.0.8",
|
|
38
38
|
"modal-cropper": "^1.2.3",
|
|
39
39
|
"nprogress": "^0.2.0",
|
|
40
40
|
"prettysize": "^2.0.0",
|
|
41
41
|
"react-admin-base": "^0.7.3",
|
|
42
42
|
"react-password-strength-bar": "^0.4.1",
|
|
43
|
-
"react-responsive": "^
|
|
44
|
-
"react-select": "^5.
|
|
45
|
-
"reactstrap": "^9.1.
|
|
43
|
+
"react-responsive": "^9.0.0",
|
|
44
|
+
"react-select": "^5.4.0",
|
|
45
|
+
"reactstrap": "^9.1.4",
|
|
46
46
|
"rewire": "^6.0.0",
|
|
47
|
-
"sweetalert2": "^11.
|
|
47
|
+
"sweetalert2": "^11.5.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@types/react": "^18.0.
|
|
50
|
+
"@types/react": "^18.0.21",
|
|
51
51
|
"cross-env": "^7.0.3",
|
|
52
|
-
"nodemon": "^2.0.
|
|
53
|
-
"react-intl": "^6.
|
|
54
|
-
"typescript": "^4.
|
|
52
|
+
"nodemon": "^2.0.20",
|
|
53
|
+
"react-intl": "^6.1.2",
|
|
54
|
+
"typescript": "^4.8.4"
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/** @jsx jsx */
|
|
2
|
-
import { jsx } from '@emotion/react';
|
|
3
|
-
import React, { useCallback, useMemo, useState } from 'react';
|
|
4
|
-
import { useFetch } from 'react-admin-base';
|
|
5
|
-
import { FormattedMessage, useIntl } from 'react-intl';
|
|
6
|
-
import Select, { components } from "react-select";
|
|
7
|
-
import CreatableSelect from 'react-select/creatable';
|
|
2
|
+
import { jsx } from '@emotion/react';
|
|
3
|
+
import React, { useCallback, useMemo, useState } from 'react';
|
|
4
|
+
import { useFetch } from 'react-admin-base';
|
|
5
|
+
import { FormattedMessage, useIntl } from 'react-intl';
|
|
6
|
+
import Select, { components } from "react-select";
|
|
7
|
+
import CreatableSelect from 'react-select/creatable';
|
|
8
8
|
|
|
9
9
|
function Option(props) {
|
|
10
10
|
return <components.Option {...props}>
|
|
@@ -60,7 +60,25 @@ function IndicatorsContainer(props) {
|
|
|
60
60
|
|
|
61
61
|
const Components = { Option, SingleValue, IndicatorsContainer };
|
|
62
62
|
|
|
63
|
-
export
|
|
63
|
+
export interface ApiSelectProps<Option = any> {
|
|
64
|
+
url?: string;
|
|
65
|
+
value: Option|Option[];
|
|
66
|
+
onChange: (a: Option|Option[]|null) => void;
|
|
67
|
+
getOptionLabel?: (a: any) => string;
|
|
68
|
+
getOptionValue?: (a: any) => string;
|
|
69
|
+
onCreateOption?: (a: string) => Option|Promise<Option>;
|
|
70
|
+
filter?: (a: Option) => boolean;
|
|
71
|
+
group?: (a: Option[]) => any[];
|
|
72
|
+
isMulti?: boolean;
|
|
73
|
+
idKey?: string;
|
|
74
|
+
nameKey?: string;
|
|
75
|
+
disabled?: boolean;
|
|
76
|
+
placeholder?: string;
|
|
77
|
+
staticOptions?: any[];
|
|
78
|
+
getNewOptionData?: (name: string, elem: React.ReactNode) => any|null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export default function ApiSelect<Option = any>(props: ApiSelectProps<Option>) {
|
|
64
82
|
const { disabled, url, getOptionLabel, getOptionValue, idKey, nameKey, filter, group, onCreateOption, getNewOptionData, isMulti, onChange, value, placeholder, staticOptions } = props;
|
|
65
83
|
const intl = useIntl();
|
|
66
84
|
const [ search, setSearch ] = useState('');
|
|
@@ -76,11 +94,14 @@ export default function ApiSelect(props) {
|
|
|
76
94
|
}
|
|
77
95
|
|
|
78
96
|
const handleCreateOption = useCallback(async function(input) {
|
|
97
|
+
if (!onCreateOption)
|
|
98
|
+
return null;
|
|
99
|
+
|
|
79
100
|
setCreating(true);
|
|
80
101
|
try {
|
|
81
102
|
let option = await onCreateOption(input);
|
|
82
103
|
if (isMulti) {
|
|
83
|
-
onChange((value || []).concat([option]));
|
|
104
|
+
onChange(((value as Option[]) || []).concat([option]));
|
|
84
105
|
} else {
|
|
85
106
|
onChange(option);
|
|
86
107
|
}
|
|
@@ -104,8 +125,8 @@ export default function ApiSelect(props) {
|
|
|
104
125
|
{...props}
|
|
105
126
|
className='react-select-container'
|
|
106
127
|
classNamePrefix="react-select"
|
|
107
|
-
onCreateOption={
|
|
108
|
-
getNewOptionData={onCreateOption
|
|
128
|
+
onCreateOption={onCreateOption && handleCreateOption}
|
|
129
|
+
getNewOptionData={(onCreateOption && (getNewOptionData || ((inputValue) =>( { [nameKey || 'name']: inputValue, __isNew__: true })))) || undefined}
|
|
109
130
|
inputValue={search}
|
|
110
131
|
onInputChange={a => setSearch(a)}
|
|
111
132
|
components={Components}
|
|
@@ -117,7 +138,6 @@ export default function ApiSelect(props) {
|
|
|
117
138
|
isSearchable
|
|
118
139
|
placeholder={placeholder || intl.formatMessage({ id: 'SELECT' })}
|
|
119
140
|
options={!options ? [] : ((filter && options.filter(filter)) || options)}
|
|
120
|
-
isMenuOpen={isMenuOpen}
|
|
121
141
|
onMenuOpen={onMenuOpen}
|
|
122
142
|
onMenuClose={onMenuClose}
|
|
123
143
|
/>;
|
|
@@ -7,12 +7,21 @@ import Swal from 'sweetalert2';
|
|
|
7
7
|
import BootstrapPagination from "./BootstrapPagination";
|
|
8
8
|
|
|
9
9
|
const DataTableContext = React.createContext(null as any);
|
|
10
|
+
const RowDatasContext = React.createContext(null as any);
|
|
11
|
+
const RowDataContext = React.createContext(null as any);
|
|
10
12
|
|
|
11
13
|
export function useDataTableContext() {
|
|
12
14
|
return useContext(DataTableContext);
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
type ActionsProp = {
|
|
18
|
+
edit?: string;
|
|
19
|
+
del?: string;
|
|
20
|
+
rowSpan?: number|undefined;
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export function Actions({edit, del, rowSpan, children}: ActionsProp) {
|
|
16
25
|
const [api] = useAuth();
|
|
17
26
|
const [, setParams] = useContext(DataTableContext);
|
|
18
27
|
const intl = useIntl();
|
|
@@ -75,14 +84,39 @@ export function Column(props) {
|
|
|
75
84
|
</th>;
|
|
76
85
|
}
|
|
77
86
|
|
|
78
|
-
export
|
|
79
|
-
|
|
87
|
+
export interface BootstrapTableProps {
|
|
88
|
+
url: string;
|
|
89
|
+
bordered?: boolean;
|
|
90
|
+
noStrip?: boolean;
|
|
91
|
+
defaultParams?: any;
|
|
92
|
+
body?: any;
|
|
93
|
+
add?: string;
|
|
94
|
+
children: any;
|
|
95
|
+
innerRef?: any;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface RowRendererProps<Row = any> {
|
|
99
|
+
render: (row: Row) => React.ReactNode;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function RowRenderer<Row = any>({render}: RowRendererProps<Row>) {
|
|
103
|
+
const rows = useContext(RowDatasContext);
|
|
104
|
+
|
|
105
|
+
return <tbody>
|
|
106
|
+
{ rows.map(render) }
|
|
107
|
+
</tbody>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export default function BootstrapTable({url, bordered, noStrip, defaultParams, add, children, innerRef, body}: BootstrapTableProps) {
|
|
111
|
+
const state = useState({sort: 'id', ...defaultParams});
|
|
80
112
|
const [params, setParams] = state;
|
|
81
113
|
const [page, lastPage, setPage, data, itemPerPage, setItemPerPage, update] = useDataTable(url, params, body);
|
|
82
114
|
const intl = useIntl();
|
|
83
115
|
const [ api ] = useAuth();
|
|
84
116
|
|
|
85
|
-
|
|
117
|
+
console.log(children[1]);
|
|
118
|
+
|
|
119
|
+
const ref = useRef(defaultParams);
|
|
86
120
|
useEffect(function () {
|
|
87
121
|
if (ref.current !== defaultParams) {
|
|
88
122
|
ref.current = defaultParams;
|
|
@@ -114,47 +148,49 @@ export default function BootstrapTable({url, bordered, noStrip, defaultParams, a
|
|
|
114
148
|
<DataTableContext.Provider value={state}>
|
|
115
149
|
<DataContextProvider value={fetchData}>
|
|
116
150
|
<RefreshScope update={update}>
|
|
117
|
-
<
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
<
|
|
122
|
-
<
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
<
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
151
|
+
<RowDatasContext.Provider value={data}>
|
|
152
|
+
<CardHeader>
|
|
153
|
+
<Row>
|
|
154
|
+
{add && <Col xs="12" md="2"><Link to={add} className="btn btn-primary font-xl d-block"><i className="fa fa-plus"/></Link></Col>}
|
|
155
|
+
<Col md="2">
|
|
156
|
+
<Input type="select" value={itemPerPage.toString()} onChange={a => setItemPerPage(+a.currentTarget.value)}>
|
|
157
|
+
<option value="1">1</option>
|
|
158
|
+
<option value="20">20</option>
|
|
159
|
+
<option value="50">50</option>
|
|
160
|
+
<option value="100">100</option>
|
|
161
|
+
<option value="150">150</option>
|
|
162
|
+
<option value="200">200</option>
|
|
163
|
+
<option value="-1">{intl.formatMessage({id: "ALL"})}</option>
|
|
164
|
+
</Input>
|
|
165
|
+
</Col>
|
|
166
|
+
{children[2]}
|
|
167
|
+
<Col md="3" className="ms-auto">
|
|
168
|
+
<Input
|
|
169
|
+
placeholder={intl.formatMessage({id: "SEARCH"})} type="text"
|
|
170
|
+
value={params.query || ''}
|
|
171
|
+
onChange={e => setParams({...params, query: e.currentTarget.value})}
|
|
172
|
+
/>
|
|
173
|
+
</Col>
|
|
174
|
+
</Row>
|
|
175
|
+
</CardHeader>
|
|
176
|
+
{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">
|
|
177
|
+
<i className="far fa-times-circle"></i> <FormattedMessage id="NO_DATA_IS_AVAILABLE"/>
|
|
178
|
+
</Alert> : <Table hover bordered={bordered} striped={!noStrip} responsive size="md" className="mb-0 dataTable">
|
|
179
|
+
{children[0]}
|
|
180
|
+
{children[1].type === "tbody" ? <tbody>
|
|
181
|
+
{data && data.map(children[1].props.children)}
|
|
182
|
+
</tbody> : children[1]}
|
|
183
|
+
</Table>}
|
|
184
|
+
{ lastPage > 1 && <CardFooter>
|
|
185
|
+
<nav>
|
|
186
|
+
<BootstrapPagination
|
|
187
|
+
currentPage={page}
|
|
188
|
+
pageCount={lastPage}
|
|
189
|
+
onPageChange={index => setPage(index)}
|
|
137
190
|
/>
|
|
138
|
-
</
|
|
139
|
-
</
|
|
140
|
-
</
|
|
141
|
-
{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">
|
|
142
|
-
<i className="far fa-times-circle"></i> <FormattedMessage id="NO_DATA_IS_AVAILABLE"/>
|
|
143
|
-
</Alert> : <Table hover bordered={bordered} striped={!noStrip} responsive size="md" className="mb-0 dataTable">
|
|
144
|
-
{children[0]}
|
|
145
|
-
<tbody>
|
|
146
|
-
{data && data.map(children[1].props.children)}
|
|
147
|
-
</tbody>
|
|
148
|
-
</Table>}
|
|
149
|
-
{ lastPage > 1 && <CardFooter>
|
|
150
|
-
<nav>
|
|
151
|
-
<BootstrapPagination
|
|
152
|
-
currentPage={page}
|
|
153
|
-
pageCount={lastPage}
|
|
154
|
-
onPageChange={index => setPage(index)}
|
|
155
|
-
/>
|
|
156
|
-
</nav>
|
|
157
|
-
</CardFooter> }
|
|
191
|
+
</nav>
|
|
192
|
+
</CardFooter> }
|
|
193
|
+
</RowDatasContext.Provider>
|
|
158
194
|
</RefreshScope>
|
|
159
195
|
</DataContextProvider>
|
|
160
196
|
</DataTableContext.Provider>
|
package/src/Components/CRUD.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import { FormattedMessage } from 'react-intl';
|
|
|
4
4
|
import { Navigate, Routes, useParams, Route } from 'react-router-dom';
|
|
5
5
|
import { Alert, Button, Col, Form, Modal, ModalFooter, ModalHeader, Row } from "reactstrap";
|
|
6
6
|
import LoadingButton from '../Components/LoadingButton';
|
|
7
|
-
import BootstrapDataTable, { Actions } from './BootstrapDataTable';
|
|
7
|
+
import BootstrapDataTable, { Actions, BootstrapTableProps } from './BootstrapDataTable';
|
|
8
8
|
|
|
9
9
|
type ModalEntityEditorParams = {
|
|
10
10
|
entity: any;
|
|
@@ -109,11 +109,17 @@ function ComponentWrapper({ Component, ...props }) {
|
|
|
109
109
|
return <Component {...props} id={id} />;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
interface CRUDProps extends BootstrapTableProps {
|
|
113
|
+
apiUrl?: string;
|
|
114
|
+
Component: any;
|
|
115
|
+
noAdd?: boolean;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export default function CRUD(props: CRUDProps) {
|
|
113
119
|
const ref = useRef(null as any);
|
|
114
120
|
const { url, apiUrl, Component, defaultParams, noAdd } = props;
|
|
115
121
|
|
|
116
|
-
|
|
122
|
+
const reload = useCallback(async function() {
|
|
117
123
|
if (ref.current) {
|
|
118
124
|
ref.current({});
|
|
119
125
|
}
|
|
@@ -124,6 +130,6 @@ export default function CRUD(props) {
|
|
|
124
130
|
{ !noAdd && <Route path="create" element={<ComponentWrapper Component={Component} url={url} onReload={reload} {...(defaultParams || {})} />} /> }
|
|
125
131
|
<Route path=":id/edit" element={<ComponentWrapper Component={Component} url={url} onReload={reload} {...(defaultParams || {})} />} />
|
|
126
132
|
</Routes>
|
|
127
|
-
<BootstrapDataTable innerRef={ref} add={!noAdd && "create"} {...props} url={apiUrl || url} />
|
|
133
|
+
<BootstrapDataTable innerRef={ref} add={(!noAdd && "create") || undefined} {...props} url={apiUrl || url} />
|
|
128
134
|
</UrlContext.Provider>;
|
|
129
135
|
}
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { FormGroup, Input, Label } from "reactstrap";
|
|
2
|
+
import { FormGroup, Input, InputProps, Label } from "reactstrap";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
interface CheckBoxProps extends InputProps {
|
|
5
|
+
id: string;
|
|
6
|
+
type?: "checkbox"|"radio";
|
|
7
|
+
label?: React.ReactNode;
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default function CheckBox(props: CheckBoxProps) {
|
|
5
12
|
return <FormGroup check>
|
|
6
|
-
<Input type={props.type || "checkbox"} {...props} label={undefined} />
|
|
13
|
+
<Input type={props.type || "checkbox"} {...props} children={undefined} label={undefined} />
|
|
7
14
|
<Label check for={props.id}>{props.children || props.label}</Label>
|
|
8
15
|
</FormGroup>;
|
|
9
16
|
}
|
|
@@ -3,7 +3,11 @@ import { ValidatorOptionProvider } from "react-admin-base";
|
|
|
3
3
|
import { useIntl } from "react-intl";
|
|
4
4
|
import zxcvbn from 'zxcvbn';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
type DefaultValidatorOptionsProps = {
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default function DefaultValidatorOptions({ children }: DefaultValidatorOptionsProps) {
|
|
7
11
|
const intl = useIntl();
|
|
8
12
|
|
|
9
13
|
const options = useMemo(() => ({
|
|
@@ -5,7 +5,9 @@ import {Button, Col} from "reactstrap";
|
|
|
5
5
|
export default function ExcelExportButton({name, header, params, size, map, extra}) {
|
|
6
6
|
const [ handleExport, loading ] = useExporter(header, params, map, extra);
|
|
7
7
|
|
|
8
|
-
return <Col
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
return <Col>
|
|
9
|
+
<Button className="w-100 d-block" type="button" size={size} color="success" outline disabled={!!loading} onClick={() => handleExport(name)}>
|
|
10
|
+
{loading ? <i className="fas fa-spin fa-spinner"/> : <i className="fas fa-file-excel"/>}
|
|
11
|
+
</Button>
|
|
12
|
+
</Col>;
|
|
11
13
|
}
|
|
@@ -3,7 +3,14 @@ import React from 'react';
|
|
|
3
3
|
import { useApp, useAuth, useLogin } from 'react-admin-base';
|
|
4
4
|
import { FormattedMessage } from 'react-intl';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
type ExternalLoginButtonProps = {
|
|
7
|
+
id: string;
|
|
8
|
+
icon?: string;
|
|
9
|
+
name: string;
|
|
10
|
+
url: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default function ExternalLoginButton({ id, icon, name, url }: ExternalLoginButtonProps) {
|
|
7
14
|
const { endpoint } = useApp();
|
|
8
15
|
const [{ client_id }] = useAuth();
|
|
9
16
|
const { login } = useLogin();
|
|
@@ -5,7 +5,7 @@ import {Button} from "reactstrap";
|
|
|
5
5
|
import { useApp, useFilePicker, usePreviewComponent } from "react-admin-base";
|
|
6
6
|
import {FormattedMessage} from "react-intl";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const photo_ext = ["png", "jpg", "jpeg", "svg"];
|
|
9
9
|
|
|
10
10
|
function is_photo(name) {
|
|
11
11
|
return photo_ext.indexOf(name.split('.')[1]) !== -1;
|
|
@@ -15,11 +15,15 @@ function is_absolute(url) {
|
|
|
15
15
|
if (url.indexOf("blob:") === 0)
|
|
16
16
|
return false;
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
const pat = /^https?:\/\//i;
|
|
19
19
|
return !pat.test(url);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
type RelativeProps = {
|
|
23
|
+
children: JSX.Element;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export function Relative({ children }: RelativeProps) {
|
|
23
27
|
const app = useApp();
|
|
24
28
|
|
|
25
29
|
if (!children)
|
|
@@ -34,8 +38,8 @@ export function Relative({ children }) {
|
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
export function Preview({ value }) {
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
const name = value.$name;
|
|
42
|
+
const src = value.$blob_url || value.$src;
|
|
39
43
|
|
|
40
44
|
if (is_photo(name)) {
|
|
41
45
|
return <div className="mt-2">
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
|
|
2
2
|
import React, { useCallback } from 'react';
|
|
3
|
-
import SingleFilePicker from './SingleFilePicker';
|
|
3
|
+
import SingleFilePicker, { SingleFilePickerProps } from './SingleFilePicker';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
interface ImagePickerProps extends SingleFilePickerProps {
|
|
6
6
|
width: number;
|
|
7
7
|
height: number;
|
|
8
8
|
type: string;
|
|
9
9
|
exact?: boolean;
|
|
10
|
-
}
|
|
10
|
+
}
|
|
11
11
|
|
|
12
|
-
export default function ImagePicker(props) {
|
|
12
|
+
export default function ImagePicker(props: ImagePickerProps) {
|
|
13
13
|
const { width, height, type, exact } = props;
|
|
14
14
|
|
|
15
15
|
const transform = useCallback(async function(file) {
|
|
@@ -20,7 +20,14 @@ export function useLanguage() {
|
|
|
20
20
|
return useContext(LanguageContext);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
type LanguageProviderProps = {
|
|
24
|
+
defaultLanguage: string;
|
|
25
|
+
languages: any;
|
|
26
|
+
loader?: (language: any) => any;
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default function LanguageProvider({ defaultLanguage, languages, loader, children }: LanguageProviderProps) {
|
|
24
31
|
const app = useApp();
|
|
25
32
|
|
|
26
33
|
const preferredLanguage = (navigator.languages && navigator.languages[0]) || navigator.language;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { Button } from 'reactstrap';
|
|
3
|
+
import { Button, ButtonProps } from 'reactstrap';
|
|
4
4
|
|
|
5
|
-
export default function LoadingButton(props) {
|
|
5
|
+
export default function LoadingButton(props: ButtonProps) {
|
|
6
6
|
return props.loading ? <Button {...props} loading={undefined} disabled={true}><i className="fas fa-spin fa-circle-notch" /></Button> : <Button {...props} loading={undefined} />;
|
|
7
7
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
import React, { useCallback, useMemo } from 'react';
|
|
3
|
-
import { useUploadController } from "react-admin-base";
|
|
4
|
-
import FilePickerCore from "./FilePickerCore";
|
|
2
|
+
import React, { useCallback, useMemo } from 'react';
|
|
3
|
+
import { useUploadController } from "react-admin-base";
|
|
4
|
+
import FilePickerCore from "./FilePickerCore";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
export interface SingleFilePickerProps {
|
|
7
7
|
disabled?: boolean;
|
|
8
8
|
className?: string;
|
|
9
9
|
accepts?: string;
|
|
@@ -4,7 +4,13 @@ import { FormattedMessage } from "react-intl";
|
|
|
4
4
|
const IndexContext = React.createContext(0);
|
|
5
5
|
const OnClickDataContext = React.createContext<[number, (a: Number) => void]>(null as any);
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
type StepListProps = {
|
|
8
|
+
active: number;
|
|
9
|
+
setActive: (active: number) => {};
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default function StepList({ active, setActive, children }: StepListProps) {
|
|
8
14
|
const onClickData = useMemo<[number, (a: Number) => void]>(() => [active, setActive], [active, setActive]);
|
|
9
15
|
|
|
10
16
|
return <ul className="step step-sm step-icon-sm step step-inline step-item-between mb-3">
|
|
@@ -18,7 +24,13 @@ export default function StepList({ active, setActive, children }: any) {
|
|
|
18
24
|
</ul>;
|
|
19
25
|
}
|
|
20
26
|
|
|
21
|
-
|
|
27
|
+
type StepItemProps = {
|
|
28
|
+
title?: string;
|
|
29
|
+
translate?: string;
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function StepItem({ title, translate, disabled }: StepItemProps) {
|
|
22
34
|
const index = useContext(IndexContext);
|
|
23
35
|
const [ activeStep, onClickParent ] = useContext(OnClickDataContext);
|
|
24
36
|
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import NProgress from 'nprogress';
|
|
2
|
-
import { useEffect } from 'react';
|
|
2
|
+
import React, { useEffect } from 'react';
|
|
3
3
|
import { useAuth } from "react-admin-base";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
type TopProgressBarProps = {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export default function TopProgressBar({ children }: TopProgressBarProps): React.ReactNode {
|
|
6
10
|
const [ api ] = useAuth();
|
|
7
11
|
|
|
8
12
|
useEffect(function() {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import { useValidate, useValidator } from 'react-admin-base';
|
|
4
|
-
import { FormattedMessage } from "react-intl";
|
|
5
|
-
import { Alert, FormFeedback } from "reactstrap";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useValidate, useValidator } from 'react-admin-base';
|
|
4
|
+
import { FormattedMessage } from "react-intl";
|
|
5
|
+
import { Alert, FormFeedback } from "reactstrap";
|
|
6
6
|
|
|
7
7
|
function ValidatorCore(name: string, value: any, type: any, children: any) {
|
|
8
8
|
const error = useValidate(name || '', value, type);
|
|
@@ -17,7 +17,7 @@ function ValidatorCore(name: string, value: any, type: any, children: any) {
|
|
|
17
17
|
type ValidatorProps = {
|
|
18
18
|
name: string;
|
|
19
19
|
type: any;
|
|
20
|
-
children:
|
|
20
|
+
children: JSX.Element;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
export function Validator({ name, type, children }: ValidatorProps) {
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import BootstrapTable, { Actions, ActionsColumn, Column, default as BootstrapDataTable, IdColumn, useDataTableContext } from './Components/BootstrapDataTable';
|
|
2
|
+
import BootstrapTable, { RowRenderer, Actions, ActionsColumn, Column, default as BootstrapDataTable, IdColumn, useDataTableContext } from './Components/BootstrapDataTable';
|
|
3
3
|
import CRUD, { CRUDActions, ModalEntityEditor } from './Components/CRUD';
|
|
4
4
|
import EntityEditor from "./Components/EntityEditor";
|
|
5
5
|
import ExcelExportButton from './Components/ExcelExportButton';
|
|
@@ -44,6 +44,7 @@ export {
|
|
|
44
44
|
Validator, ValueValidator, ValidationErrors,
|
|
45
45
|
LoadingButton,
|
|
46
46
|
BootstrapDataTable, IdColumn, Column, ActionsColumn, Actions, useDataTableContext,
|
|
47
|
+
RowRenderer,
|
|
47
48
|
LanguageProvider, useLanguage, LanguageSwitcher,
|
|
48
49
|
ErrorBoundary,
|
|
49
50
|
CheckBox
|