react-admin-base-bootstrap 0.9.3 → 0.9.5
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/bun.lockb
CHANGED
|
Binary file
|
|
@@ -14,6 +14,7 @@ export interface ApiSelectProps<Option = any> {
|
|
|
14
14
|
disabled?: boolean;
|
|
15
15
|
placeholder?: string;
|
|
16
16
|
staticOptions?: any[];
|
|
17
|
+
sortable?: boolean;
|
|
17
18
|
onAddOrEdit?: (item: any) => void;
|
|
18
19
|
getNewOptionData?: (name: string, elem: React.ReactNode) => any | null;
|
|
19
20
|
}
|
|
@@ -12,6 +12,12 @@ import { RefreshScope, useFetch, useRefresh } from 'react-admin-base';
|
|
|
12
12
|
import { FormattedMessage, useIntl } from 'react-intl';
|
|
13
13
|
import Select, { components } from "react-select";
|
|
14
14
|
import CreatableSelect from 'react-select/creatable';
|
|
15
|
+
import { SortableContainer, SortableElement, SortableHandle, } from 'react-sortable-hoc';
|
|
16
|
+
function arrayMove(array, from, to) {
|
|
17
|
+
const slicedArray = array.slice();
|
|
18
|
+
slicedArray.splice(to < 0 ? array.length + to : to, 0, slicedArray.splice(from, 1)[0]);
|
|
19
|
+
return slicedArray;
|
|
20
|
+
}
|
|
15
21
|
function Option(props) {
|
|
16
22
|
return React.createElement(components.Option, Object.assign({}, props), (props.selectProps.children && props.selectProps.children(props.data)) || (props.data.__isNew__ ? React.createElement(FormattedMessage, { id: "CREATE_VALUE", values: { text: props.children } }) : props.children));
|
|
17
23
|
}
|
|
@@ -47,8 +53,20 @@ function MultiValueRemove(props) {
|
|
|
47
53
|
React.createElement(components.MultiValueRemove, Object.assign({}, props)));
|
|
48
54
|
}
|
|
49
55
|
const Components = { Option, SingleValue, MultiValue, IndicatorsContainer, MultiValueRemove };
|
|
56
|
+
const SortableMultiValue = SortableElement((props) => {
|
|
57
|
+
const onMouseDown = (e) => {
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
e.stopPropagation();
|
|
60
|
+
};
|
|
61
|
+
const innerProps = Object.assign(Object.assign({}, props.innerProps), { onMouseDown });
|
|
62
|
+
return React.createElement(MultiValue, Object.assign({}, props, { innerProps: innerProps }));
|
|
63
|
+
});
|
|
64
|
+
const SortableMultiValueLabel = SortableHandle((props) => React.createElement(components.MultiValueLabel, Object.assign({}, props)));
|
|
65
|
+
const SortableComponents = { Option, SingleValue, MultiValue: SortableMultiValue, MultiValueLabel: SortableMultiValueLabel, IndicatorsContainer, MultiValueRemove };
|
|
66
|
+
const SortableSelect = SortableContainer(Select);
|
|
67
|
+
const SortableCreateableSelect = SortableContainer(CreatableSelect);
|
|
50
68
|
export default function ApiSelect(props) {
|
|
51
|
-
const { disabled, url, getOptionLabel, getOptionValue, idKey, nameKey, filter, group, onCreateOption, getNewOptionData, isMulti, onChange, value, placeholder, staticOptions } = props;
|
|
69
|
+
const { disabled, url, getOptionLabel, sortable, getOptionValue, idKey, nameKey, filter, group, onCreateOption, getNewOptionData, isMulti, onChange, value, placeholder, staticOptions } = props;
|
|
52
70
|
const intl = useIntl();
|
|
53
71
|
const [search, setSearch] = useState('');
|
|
54
72
|
const params = useMemo(() => ({ query: search }), [search]);
|
|
@@ -86,9 +104,13 @@ export default function ApiSelect(props) {
|
|
|
86
104
|
const onMenuClose = useCallback(function () {
|
|
87
105
|
setIsMenuOpen(false);
|
|
88
106
|
}, [setIsMenuOpen]);
|
|
89
|
-
const
|
|
107
|
+
const onSortEnd = useCallback(({ oldIndex, newIndex }) => {
|
|
108
|
+
const newValue = arrayMove(value, oldIndex, newIndex);
|
|
109
|
+
onChange(newValue);
|
|
110
|
+
}, [value, onChange]);
|
|
111
|
+
const Component = (onCreateOption ? (sortable && isMulti ? SortableCreateableSelect : CreatableSelect) : (sortable && isMulti ? SortableSelect : Select));
|
|
90
112
|
return React.createElement(RefreshScope, { update: update },
|
|
91
|
-
React.createElement(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 })));
|
|
113
|
+
React.createElement(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: (isMulti && sortable ? SortableComponents : 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, axis: "xy", onSortEnd: onSortEnd, distance: 4, getHelperDimensions: ({ node }) => node.getBoundingClientRect() })));
|
|
92
114
|
}
|
|
93
115
|
export function CreateSelect(props) {
|
|
94
116
|
const { Component, onChange, value, isMulti, idKey } = props;
|
|
@@ -98,7 +98,7 @@ export function ModalEntityEditor({ entity, title, size, url, onReload, disabled
|
|
|
98
98
|
' ',
|
|
99
99
|
React.createElement(FormattedMessage, { id: "ENTITY.SAVE" }))),
|
|
100
100
|
React.createElement(Col, null,
|
|
101
|
-
React.createElement(Button, { block: true, outline: true, color: "danger", onClick:
|
|
101
|
+
React.createElement(Button, { type: "button", block: true, outline: true, color: "danger", onClick: onClose },
|
|
102
102
|
React.createElement("i", { className: "fas fa-times-circle" }),
|
|
103
103
|
' ',
|
|
104
104
|
React.createElement(FormattedMessage, { id: "ENTITY.CANCEL" })))))))));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-admin-base-bootstrap",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.5",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
@@ -38,12 +38,13 @@
|
|
|
38
38
|
"modal-cropper": "^1.2.3",
|
|
39
39
|
"nprogress": "^0.2.0",
|
|
40
40
|
"prettysize": "^2.0.0",
|
|
41
|
-
"react-admin-base": "^0.9.
|
|
41
|
+
"react-admin-base": "^0.9.1",
|
|
42
42
|
"react-dnd": "^16.0.1",
|
|
43
43
|
"react-dnd-html5-backend": "^16.0.1",
|
|
44
44
|
"react-password-strength-bar": "^0.4.1",
|
|
45
45
|
"react-responsive": "^9.0.2",
|
|
46
46
|
"react-select": "^5.8.0",
|
|
47
|
+
"react-sortable-hoc": "^2.0.0",
|
|
47
48
|
"reactstrap": "^9.2.2",
|
|
48
49
|
"sweetalert2": "^11.10.4"
|
|
49
50
|
},
|
|
@@ -5,6 +5,25 @@ import { FormattedMessage, useIntl } from 'react-intl';
|
|
|
5
5
|
import Select, { components } from "react-select";
|
|
6
6
|
import CreatableSelect from 'react-select/creatable';
|
|
7
7
|
|
|
8
|
+
import {
|
|
9
|
+
SortableContainer,
|
|
10
|
+
SortableContainerProps,
|
|
11
|
+
SortableElement,
|
|
12
|
+
SortEndHandler,
|
|
13
|
+
SortableHandle,
|
|
14
|
+
} from 'react-sortable-hoc';
|
|
15
|
+
|
|
16
|
+
function arrayMove<T>(array: readonly T[], from: number, to: number) {
|
|
17
|
+
const slicedArray = array.slice();
|
|
18
|
+
slicedArray.splice(
|
|
19
|
+
to < 0 ? array.length + to : to,
|
|
20
|
+
0,
|
|
21
|
+
slicedArray.splice(from, 1)[0]
|
|
22
|
+
);
|
|
23
|
+
return slicedArray;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
8
27
|
function Option(props) {
|
|
9
28
|
return <components.Option {...props}>
|
|
10
29
|
{ (props.selectProps.children && props.selectProps.children(props.data)) || (props.data.__isNew__ ? <FormattedMessage
|
|
@@ -42,7 +61,7 @@ function EditOrAddIndicator(props) {
|
|
|
42
61
|
className
|
|
43
62
|
)}
|
|
44
63
|
css={getStyles('clearIndicator', props)}
|
|
45
|
-
onMouseDown={e => {
|
|
64
|
+
onMouseDown={e => {
|
|
46
65
|
e.stopPropagation();
|
|
47
66
|
e.preventDefault();
|
|
48
67
|
props.selectProps.onAddOrEdit();
|
|
@@ -73,6 +92,26 @@ function MultiValueRemove(props) {
|
|
|
73
92
|
|
|
74
93
|
const Components = { Option, SingleValue, MultiValue, IndicatorsContainer, MultiValueRemove };
|
|
75
94
|
|
|
95
|
+
const SortableMultiValue = SortableElement(
|
|
96
|
+
(props) => {
|
|
97
|
+
const onMouseDown = (e) => {
|
|
98
|
+
e.preventDefault();
|
|
99
|
+
e.stopPropagation();
|
|
100
|
+
};
|
|
101
|
+
const innerProps = { ...props.innerProps, onMouseDown };
|
|
102
|
+
return <MultiValue {...props} innerProps={innerProps} />;
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const SortableMultiValueLabel = SortableHandle(
|
|
107
|
+
(props) => <components.MultiValueLabel {...props} />
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const SortableComponents = { Option, SingleValue, MultiValue: SortableMultiValue, MultiValueLabel: SortableMultiValueLabel, IndicatorsContainer, MultiValueRemove };
|
|
111
|
+
|
|
112
|
+
const SortableSelect = SortableContainer(Select);
|
|
113
|
+
const SortableCreateableSelect = SortableContainer(CreatableSelect);
|
|
114
|
+
|
|
76
115
|
export interface ApiSelectProps<Option = any> {
|
|
77
116
|
url?: string;
|
|
78
117
|
value: Option|Option[];
|
|
@@ -88,12 +127,14 @@ export interface ApiSelectProps<Option = any> {
|
|
|
88
127
|
disabled?: boolean;
|
|
89
128
|
placeholder?: string;
|
|
90
129
|
staticOptions?: any[];
|
|
130
|
+
sortable?: boolean;
|
|
91
131
|
onAddOrEdit?: (item: any) => void;
|
|
92
132
|
getNewOptionData?: (name: string, elem: React.ReactNode) => any|null;
|
|
93
133
|
}
|
|
94
134
|
|
|
135
|
+
|
|
95
136
|
export default function ApiSelect<Option = any>(props: ApiSelectProps<Option>) {
|
|
96
|
-
const { disabled, url, getOptionLabel, getOptionValue, idKey, nameKey, filter, group, onCreateOption, getNewOptionData, isMulti, onChange, value, placeholder, staticOptions } = props;
|
|
137
|
+
const { disabled, url, getOptionLabel, sortable, getOptionValue, idKey, nameKey, filter, group, onCreateOption, getNewOptionData, isMulti, onChange, value, placeholder, staticOptions } = props;
|
|
97
138
|
const intl = useIntl();
|
|
98
139
|
const [ search, setSearch ] = useState('');
|
|
99
140
|
const params = useMemo(() => ({ query: search }), [search]);
|
|
@@ -133,18 +174,23 @@ export default function ApiSelect<Option = any>(props: ApiSelectProps<Option>) {
|
|
|
133
174
|
setIsMenuOpen(false);
|
|
134
175
|
}, [ setIsMenuOpen ]);
|
|
135
176
|
|
|
136
|
-
const
|
|
177
|
+
const onSortEnd: SortEndHandler = useCallback(({ oldIndex, newIndex }) => {
|
|
178
|
+
const newValue = arrayMove(value as any, oldIndex, newIndex);
|
|
179
|
+
onChange(newValue as any);
|
|
180
|
+
}, [ value, onChange ]);
|
|
181
|
+
|
|
182
|
+
const Component = (onCreateOption ? (sortable && isMulti ? SortableCreateableSelect : CreatableSelect) : (sortable && isMulti ? SortableSelect : Select)) as any;
|
|
137
183
|
|
|
138
184
|
return <RefreshScope update={update}>
|
|
139
185
|
<Component
|
|
140
186
|
{...props}
|
|
141
187
|
className='react-select-container'
|
|
142
188
|
classNamePrefix="react-select"
|
|
143
|
-
onCreateOption={onCreateOption && handleCreateOption}
|
|
189
|
+
onCreateOption={(onCreateOption && handleCreateOption) as any}
|
|
144
190
|
getNewOptionData={(onCreateOption && (getNewOptionData || ((inputValue) =>( { [nameKey || 'name']: inputValue, __isNew__: true })))) || undefined}
|
|
145
191
|
inputValue={search}
|
|
146
192
|
onInputChange={a => setSearch(a)}
|
|
147
|
-
components={Components}
|
|
193
|
+
components={(isMulti && sortable ? SortableComponents : Components) as any}
|
|
148
194
|
isLoading={!!loading || creating}
|
|
149
195
|
getOptionLabel={getOptionLabel || ((row:any) => row[nameKey || 'name'])}
|
|
150
196
|
getOptionValue={getOptionValue || ((row:any) => row[idKey || 'id'])}
|
|
@@ -155,6 +201,11 @@ export default function ApiSelect<Option = any>(props: ApiSelectProps<Option>) {
|
|
|
155
201
|
options={!options ? [] : ((filter && options.filter(filter)) || options)}
|
|
156
202
|
onMenuOpen={onMenuOpen}
|
|
157
203
|
onMenuClose={onMenuClose}
|
|
204
|
+
|
|
205
|
+
axis="xy"
|
|
206
|
+
onSortEnd={onSortEnd}
|
|
207
|
+
distance={4}
|
|
208
|
+
getHelperDimensions={({ node }) => node.getBoundingClientRect()}
|
|
158
209
|
/>
|
|
159
210
|
</RefreshScope>;
|
|
160
211
|
}
|
package/src/Components/CRUD.tsx
CHANGED
|
@@ -97,7 +97,7 @@ export function ModalEntityEditor({ entity, title, size, url, onReload, disabled
|
|
|
97
97
|
</LoadingButton>
|
|
98
98
|
</Col>
|
|
99
99
|
<Col>
|
|
100
|
-
<Button block outline color="danger" onClick={
|
|
100
|
+
<Button type="button" block outline color="danger" onClick={onClose}>
|
|
101
101
|
<i className="fas fa-times-circle" />{' '}<FormattedMessage id="ENTITY.CANCEL" />
|
|
102
102
|
</Button>
|
|
103
103
|
</Col>
|