@irontec/ivoz-ui 1.7.12 → 1.7.13
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/components/Dashboard/Dashboard.js +5 -5
- package/components/shared/ConfirmDialog.styles.d.ts +2 -2
- package/entities/EntityInterface.d.ts +5 -0
- package/helpers/fetchFilteredPage.d.ts +9 -0
- package/helpers/fetchFilteredPage.js +31 -0
- package/helpers/index.d.ts +2 -0
- package/helpers/index.js +2 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +1 -1
- package/services/form/Field/DynamicAutocomplete/DynamicAutocomplete.d.ts +25 -0
- package/services/form/Field/DynamicAutocomplete/DynamicAutocomplete.js +194 -0
- package/services/form/Field/DynamicAutocomplete/DynamicAutocomplete.styles.d.ts +1 -0
- package/services/form/Field/DynamicAutocomplete/DynamicAutocomplete.styles.js +6 -0
- package/services/form/Field/DynamicAutocomplete/index.d.ts +2 -0
- package/services/form/Field/DynamicAutocomplete/index.js +2 -0
- package/services/form/Field/index.d.ts +1 -0
- package/services/form/Field/index.js +1 -0
- package/services/form/FormFieldFactory/Factory/DynamicAutocompleteFactory.d.ts +22 -0
- package/services/form/FormFieldFactory/Factory/DynamicAutocompleteFactory.js +6 -0
- package/services/form/FormFieldFactory/Factory/index.d.ts +2 -1
- package/services/form/FormFieldFactory/Factory/index.js +2 -1
- package/services/form/FormFieldFactory/FormFieldFactory.d.ts +1 -0
- package/services/form/FormFieldFactory/FormFieldFactory.js +18 -1
- package/translations/ca.json +2 -0
- package/translations/en.json +3 -1
- package/translations/es.json +3 -1
- package/translations/it.json +2 -0
|
@@ -10,12 +10,12 @@ const Dashboard = (props) => {
|
|
|
10
10
|
return { name, platform, dLicences, mLicenses };
|
|
11
11
|
}
|
|
12
12
|
const rows = [
|
|
13
|
-
createData('
|
|
14
|
-
createData('
|
|
15
|
-
createData('
|
|
16
|
-
createData('
|
|
13
|
+
createData('Client 1', 'Platform A', 5, 3),
|
|
14
|
+
createData('Client 2', 'Platform B', 8, 2),
|
|
15
|
+
createData('Client 3', 'Platform C', 4, 6),
|
|
16
|
+
createData('Client 4', 'Platform D', 7, 1),
|
|
17
17
|
];
|
|
18
|
-
return (_jsxs("section", Object.assign({ className: className }, { children: [_jsx("div", Object.assign({ className: 'card welcome' }, { children: _jsxs("div", Object.assign({ className: 'card-container' }, { children: [_jsxs("div", { children: [_jsxs("h3", { children: ["Welcome to ", _jsx("br", {}), "
|
|
18
|
+
return (_jsxs("section", Object.assign({ className: className }, { children: [_jsx("div", Object.assign({ className: 'card welcome' }, { children: _jsxs("div", Object.assign({ className: 'card-container' }, { children: [_jsxs("div", { children: [_jsxs("h3", { children: ["Welcome to ", _jsx("br", {}), " Demo System"] }), _jsx("p", { children: "This is a demo. Add platforms, manage clients, assign licenses and more." }), _jsx(LightButton, { children: "Get started" })] }), _jsx("img", { src: 'assets/img/dashboard-welcome.svg' })] })) })), _jsxs("div", Object.assign({ className: 'card activity' }, { children: [_jsx("div", Object.assign({ className: 'title' }, { children: "Recent activity" })), _jsxs("div", Object.assign({ className: 'content' }, { children: [_jsxs("div", Object.assign({ className: 'row' }, { children: [_jsx("div", Object.assign({ className: 'time' }, { children: "5m" })), _jsx("div", Object.assign({ className: 'value' }, { children: "Login (User1)" }))] })), _jsxs("div", Object.assign({ className: 'row' }, { children: [_jsx("div", Object.assign({ className: 'time' }, { children: "30m" })), _jsx("div", Object.assign({ className: 'value' }, { children: "New admin added (User2)" }))] })), _jsxs("div", Object.assign({ className: 'row' }, { children: [_jsx("div", Object.assign({ className: 'time' }, { children: "6h" })), _jsx("div", Object.assign({ className: 'value' }, { children: "Login (User2)" }))] })), _jsxs("div", Object.assign({ className: 'row' }, { children: [_jsx("div", Object.assign({ className: 'time' }, { children: "1d" })), _jsx("div", Object.assign({ className: 'value' }, { children: "10 licenses assigned (User3)" }))] })), _jsxs("div", Object.assign({ className: 'row' }, { children: [_jsx("div", Object.assign({ className: 'time' }, { children: "1d" })), _jsx("div", Object.assign({ className: 'value' }, { children: "New client added (User3)" }))] }))] }))] })), _jsxs("div", Object.assign({ className: 'card amount' }, { children: [_jsx("div", Object.assign({ className: 'img-container' }, { children: _jsx(IconPlatformsDashboard, {}) })), _jsx("div", Object.assign({ className: 'number' }, { children: "4" })), _jsx("div", Object.assign({ className: 'name' }, { children: "Platforms" })), _jsxs("div", Object.assign({ className: 'progress' }, { children: [_jsx("span", { children: "+ 0" }), _jsx("img", { src: 'assets/img/same.svg' })] })), _jsx("a", Object.assign({ href: '', className: 'link' }, { children: "View platforms" }))] })), _jsxs("div", Object.assign({ className: 'card amount' }, { children: [_jsx("div", Object.assign({ className: 'img-container' }, { children: _jsx(IconClientsDashboard, {}) })), _jsx("div", Object.assign({ className: 'number' }, { children: "20" })), _jsx("div", Object.assign({ className: 'name' }, { children: "Clients" })), _jsxs("div", Object.assign({ className: 'progress' }, { children: [_jsx("span", { children: "+ 1" }), _jsx("img", { src: 'assets/img/up.svg' })] })), _jsx("a", Object.assign({ href: '', className: 'link' }, { children: "View clients" }))] })), _jsxs("div", Object.assign({ className: 'card amount' }, { children: [_jsx("div", Object.assign({ className: 'img-container' }, { children: _jsx(IconUsersDashboard, {}) })), _jsx("div", Object.assign({ className: 'number' }, { children: "100" })), _jsx("div", Object.assign({ className: 'name' }, { children: "Users" })), _jsxs("div", Object.assign({ className: 'progress' }, { children: [_jsx("span", { children: "- 2" }), _jsx("img", { src: 'assets/img/down.svg' })] })), _jsx("a", Object.assign({ href: '', className: 'link' }, { children: "View users" }))] })), _jsxs("div", Object.assign({ className: 'card licenses' }, { children: [_jsx("div", Object.assign({ className: 'title' }, { children: "Licenses" })), _jsxs("div", Object.assign({ className: 'radial' }, { children: [_jsx("div", { className: 'circle' }), _jsxs("div", Object.assign({ className: 'data' }, { children: [_jsx("div", Object.assign({ className: 'total' }, { children: "Total" })), _jsx("div", Object.assign({ className: 'number' }, { children: "120" }))] }))] })), _jsxs("div", Object.assign({ className: 'legend' }, { children: [_jsxs("div", Object.assign({ className: 'label' }, { children: [_jsx("div", { className: 'color orange' }), _jsx("div", Object.assign({ className: 'text' }, { children: "Desktop" }))] })), _jsxs("div", Object.assign({ className: 'label' }, { children: [_jsx("div", { className: 'color red' }), _jsx("div", Object.assign({ className: 'text' }, { children: "Mobile" }))] }))] }))] })), _jsxs("div", Object.assign({ className: 'card last' }, { children: [_jsxs("div", Object.assign({ className: 'header' }, { children: [_jsx("div", Object.assign({ className: 'title' }, { children: "Last added clients" })), _jsx(SolidButton, { children: "+ Add" })] })), _jsx("div", Object.assign({ className: 'table' }, { children: _jsx(TableContainer, Object.assign({ component: Paper, sx: { boxShadow: 'none' } }, { children: _jsxs(Table, Object.assign({ sx: { minWidth: 650 }, "aria-label": 'simple table' }, { children: [_jsx(TableHead, { children: _jsxs(TableRow, Object.assign({ style: { fontSize: '13px' } }, { children: [_jsx(TableCell, Object.assign({ style: { fontSize: '13px', color: 'var(--color-text)' } }, { children: "Name" })), _jsx(TableCell, Object.assign({ style: { fontSize: '13px', color: 'var(--color-text)' } }, { children: "Platform" })), _jsx(TableCell, Object.assign({ style: { fontSize: '13px', color: 'var(--color-text)' } }, { children: "Desktop licenses" })), _jsx(TableCell, Object.assign({ style: { fontSize: '13px', color: 'var(--color-text)' } }, { children: "Mobile licenses" }))] })) }), _jsx(TableBody, { children: rows.map((row) => (_jsxs(TableRow, Object.assign({ sx: { '&:last-child td, &:last-child th': { border: 0 } } }, { children: [_jsx(TableCell, Object.assign({ component: 'th', scope: 'row' }, { children: row.name })), _jsx(TableCell, { children: row.platform }), _jsx(TableCell, { children: row.dLicences }), _jsx(TableCell, { children: row.mLicenses })] }), row.name))) })] })) })) }))] }))] })));
|
|
19
19
|
};
|
|
20
20
|
export default styled(Dashboard)(({ theme }) => {
|
|
21
21
|
return {
|
|
@@ -10,8 +10,8 @@ export declare const StyledDialogContentText: import("@emotion/styled").StyledCo
|
|
|
10
10
|
noWrap?: boolean | undefined;
|
|
11
11
|
paragraph?: boolean | undefined;
|
|
12
12
|
sx?: import("@mui/material").SxProps<import("@mui/material").Theme> | undefined;
|
|
13
|
-
variant?: "button" | "caption" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "inherit" | "
|
|
14
|
-
variantMapping?: Partial<Record<"button" | "caption" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "inherit" | "
|
|
13
|
+
variant?: "button" | "caption" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "inherit" | "overline" | "subtitle1" | "subtitle2" | "body1" | "body2" | undefined;
|
|
14
|
+
variantMapping?: Partial<Record<"button" | "caption" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "inherit" | "overline" | "subtitle1" | "subtitle2" | "body1" | "body2", string>> | undefined;
|
|
15
15
|
}, "classes"> & import("@mui/material/OverridableComponent").CommonProps & Omit<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "key" | keyof import("react").HTMLAttributes<HTMLSpanElement>> & {
|
|
16
16
|
ref?: ((instance: HTMLSpanElement | null) => void) | import("react").RefObject<HTMLSpanElement> | null | undefined;
|
|
17
17
|
}, "children" | keyof import("@mui/material/OverridableComponent").CommonProps | "sx" | "variant" | "align" | ("color" | "p" | "alignContent" | "alignItems" | "alignSelf" | "bottom" | "boxShadow" | "boxSizing" | "columnGap" | "display" | "flexBasis" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "fontFamily" | "fontSize" | "fontStyle" | "fontWeight" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "height" | "justifyContent" | "justifyItems" | "justifySelf" | "left" | "letterSpacing" | "lineHeight" | "marginBottom" | "marginLeft" | "marginRight" | "marginTop" | "maxHeight" | "maxWidth" | "minHeight" | "minWidth" | "order" | "paddingBottom" | "paddingLeft" | "paddingRight" | "paddingTop" | "position" | "right" | "rowGap" | "textAlign" | "textOverflow" | "textTransform" | "top" | "visibility" | "whiteSpace" | "width" | "zIndex" | "border" | "borderBottom" | "borderColor" | "borderLeft" | "borderRadius" | "borderRight" | "borderTop" | "flex" | "gap" | "gridArea" | "gridColumn" | "gridRow" | "margin" | "overflow" | "padding" | "bgcolor" | "m" | "mt" | "mr" | "mb" | "ml" | "mx" | "marginX" | "my" | "marginY" | "pt" | "pr" | "pb" | "pl" | "px" | "paddingX" | "py" | "paddingY" | "typography" | "displayPrint") | "noWrap" | "gutterBottom" | "paragraph" | "variantMapping"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
|
|
@@ -47,6 +47,10 @@ export declare type SelectOptionsArgs = {
|
|
|
47
47
|
callback: FetchFksCallback;
|
|
48
48
|
cancelToken?: CancelToken;
|
|
49
49
|
};
|
|
50
|
+
export declare type DynamicSelectOptionsArgs = {
|
|
51
|
+
searchTerm?: string;
|
|
52
|
+
id?: string;
|
|
53
|
+
};
|
|
50
54
|
export declare type SelectOptionsType<T = any> = (props: SelectOptionsArgs, customProps?: T) => Promise<unknown>;
|
|
51
55
|
export declare type EntityAclType = {
|
|
52
56
|
iden?: string;
|
|
@@ -90,6 +94,7 @@ export default interface EntityInterface {
|
|
|
90
94
|
foreignKeyResolver: () => Promise<foreignKeyResolverType>;
|
|
91
95
|
foreignKeyGetter: () => Promise<ForeignKeyGetterType>;
|
|
92
96
|
selectOptions?: () => Promise<SelectOptionsType>;
|
|
97
|
+
dynamicSelectOptions?: boolean;
|
|
93
98
|
Form: () => Promise<React.FunctionComponent<EntityFormProps>>;
|
|
94
99
|
View: () => Promise<ViewType>;
|
|
95
100
|
List: React.FunctionComponent<ListContentProps>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CancelToken } from 'axios';
|
|
2
|
+
import { FetchFksCallback } from '../entities/EntityInterface';
|
|
3
|
+
export declare type fetchFilteredPageProps = {
|
|
4
|
+
endpoint: string;
|
|
5
|
+
params: Record<string, unknown>;
|
|
6
|
+
setter: FetchFksCallback;
|
|
7
|
+
cancelToken?: CancelToken;
|
|
8
|
+
};
|
|
9
|
+
export declare const fetchFilteredPage: (props: fetchFilteredPageProps) => Promise<unknown>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { StoreContainer } from '../store';
|
|
11
|
+
export const fetchFilteredPage = (props) => __awaiter(void 0, void 0, void 0, function* () {
|
|
12
|
+
const { endpoint, params, setter, cancelToken } = props;
|
|
13
|
+
const getAction = StoreContainer.store.getActions().api.get;
|
|
14
|
+
const response = [];
|
|
15
|
+
try {
|
|
16
|
+
yield getAction({
|
|
17
|
+
path: endpoint,
|
|
18
|
+
silenceErrors: false,
|
|
19
|
+
params: Object.assign(Object.assign({ _itemsPerPage: 20 }, params), { _pagination: true, _page: 1 }),
|
|
20
|
+
successCallback: (data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
+
response.push(...data);
|
|
22
|
+
}),
|
|
23
|
+
cancelToken,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.error(error);
|
|
28
|
+
}
|
|
29
|
+
setter(response);
|
|
30
|
+
return response;
|
|
31
|
+
});
|
package/helpers/index.js
ADDED
package/index.d.ts
CHANGED
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { InputProps } from '@mui/material';
|
|
2
|
+
import React, { JSXElementConstructor, ReactElement } from 'react';
|
|
3
|
+
import { SelectOptionsType } from 'entities/EntityInterface';
|
|
4
|
+
import { FormOnChangeEvent } from 'entities/DefaultEntityBehavior/Form/Form';
|
|
5
|
+
export interface DynamicAutocompleteProps {
|
|
6
|
+
selectOptions: (() => Promise<SelectOptionsType>) | undefined;
|
|
7
|
+
nullOption?: string | React.ReactElement<any>;
|
|
8
|
+
className?: string;
|
|
9
|
+
name: string;
|
|
10
|
+
label: string | ReactElement<any, string | JSXElementConstructor<any>>;
|
|
11
|
+
placeholder?: string;
|
|
12
|
+
value: any;
|
|
13
|
+
multiple: boolean;
|
|
14
|
+
required: boolean;
|
|
15
|
+
disabled: boolean;
|
|
16
|
+
onBlur: (event: React.FocusEvent) => void;
|
|
17
|
+
error?: boolean;
|
|
18
|
+
errorMsg?: React.ReactNode;
|
|
19
|
+
helperText?: string | React.ReactNode;
|
|
20
|
+
hasChanged: boolean;
|
|
21
|
+
InputProps?: Partial<InputProps>;
|
|
22
|
+
onChange: (event: FormOnChangeEvent) => void;
|
|
23
|
+
}
|
|
24
|
+
declare const DynamicAutocomplete: (props: DynamicAutocompleteProps) => JSX.Element | null;
|
|
25
|
+
export default DynamicAutocomplete;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Paper, Typography } from '@mui/material';
|
|
3
|
+
import MuiAutocomplete from '@mui/material/Autocomplete';
|
|
4
|
+
import { useCallback, useEffect, useState, useRef, } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { StyledAutocompleteTextField } from '../TextField';
|
|
7
|
+
import SearchIcon from '@mui/icons-material/Search';
|
|
8
|
+
const DynamicAutocomplete = (props) => {
|
|
9
|
+
var _a;
|
|
10
|
+
const { nullOption, name, label, required, multiple, disabled, onBlur, error, errorMsg, helperText, hasChanged, value, selectOptions, onChange, } = props;
|
|
11
|
+
const { t } = useTranslation();
|
|
12
|
+
let className = props.className;
|
|
13
|
+
if (hasChanged) {
|
|
14
|
+
className += ' changed';
|
|
15
|
+
}
|
|
16
|
+
if (multiple) {
|
|
17
|
+
className += ' multiselect';
|
|
18
|
+
}
|
|
19
|
+
const nullOptionObject = nullOption
|
|
20
|
+
? { id: '__null__', label: nullOption }
|
|
21
|
+
: null;
|
|
22
|
+
const [arrayChoices, setArrayChoices] = useState(nullOptionObject ? [nullOptionObject] : []);
|
|
23
|
+
const [searchTerm, setSearchTerm] = useState('');
|
|
24
|
+
const [loading, setLoading] = useState(false);
|
|
25
|
+
const [open, setOpen] = useState(false);
|
|
26
|
+
const [currentOption, setCurrentOption] = useState(nullOptionObject);
|
|
27
|
+
const debounceTimeoutRef = useRef();
|
|
28
|
+
const setOptions = useCallback((options) => {
|
|
29
|
+
const isCurrentOptionIncluded = options.some((option) => option.id == (currentOption === null || currentOption === void 0 ? void 0 : currentOption.id));
|
|
30
|
+
if (!isCurrentOptionIncluded &&
|
|
31
|
+
currentOption &&
|
|
32
|
+
currentOption.id !== '__null__') {
|
|
33
|
+
options.unshift(currentOption);
|
|
34
|
+
}
|
|
35
|
+
if (nullOptionObject) {
|
|
36
|
+
options.unshift(nullOptionObject);
|
|
37
|
+
}
|
|
38
|
+
console.log('setOptions', options);
|
|
39
|
+
setArrayChoices(options);
|
|
40
|
+
}, [nullOptionObject, currentOption]);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const hasOptions = arrayChoices.some((option) => option.id !== '__null__');
|
|
43
|
+
if (hasOptions) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const searchParams = {};
|
|
47
|
+
if (value) {
|
|
48
|
+
searchParams.id = value;
|
|
49
|
+
}
|
|
50
|
+
selectOptions === null || selectOptions === void 0 ? void 0 : selectOptions().then((selectOptions) => {
|
|
51
|
+
selectOptions({
|
|
52
|
+
callback: (options) => {
|
|
53
|
+
if (options.length > 0) {
|
|
54
|
+
setOptions(options);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
}, searchParams);
|
|
58
|
+
});
|
|
59
|
+
}, []);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (!selectOptions) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (debounceTimeoutRef.current) {
|
|
65
|
+
clearTimeout(debounceTimeoutRef.current);
|
|
66
|
+
}
|
|
67
|
+
const searchTermMatchNullOption = getOptionLabel(nullOptionObject) === searchTerm;
|
|
68
|
+
if (searchTermMatchNullOption) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const isSearchTermIncluded = arrayChoices === null || arrayChoices === void 0 ? void 0 : arrayChoices.some((option) => getOptionLabel(option).includes(searchTerm));
|
|
72
|
+
if (isSearchTermIncluded) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
setLoading(true);
|
|
76
|
+
debounceTimeoutRef.current = setTimeout(() => {
|
|
77
|
+
selectOptions().then((selectOptions) => {
|
|
78
|
+
selectOptions({
|
|
79
|
+
callback: (options) => {
|
|
80
|
+
setLoading(false);
|
|
81
|
+
setOptions(options);
|
|
82
|
+
},
|
|
83
|
+
}, {
|
|
84
|
+
searchTerm: searchTerm,
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}, 500);
|
|
88
|
+
}, [searchTerm, selectOptions]);
|
|
89
|
+
const handleInputChange = useCallback((e, value, reason) => {
|
|
90
|
+
console.log('inputChange', arrayChoices);
|
|
91
|
+
if (reason === 'clear') {
|
|
92
|
+
setSearchTerm('');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (reason === 'input') {
|
|
96
|
+
setSearchTerm(value);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (reason === 'reset') {
|
|
100
|
+
if (arrayChoices.length === 0) {
|
|
101
|
+
setSearchTerm('');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}, []);
|
|
105
|
+
const onChangeWrapper = useCallback((e, option, reason) => {
|
|
106
|
+
let selectedValue = undefined;
|
|
107
|
+
if (reason !== 'clear' && option !== null) {
|
|
108
|
+
selectedValue = multiple
|
|
109
|
+
? option.map((item) => typeof item === 'object' ? item.id : item)
|
|
110
|
+
: option.id;
|
|
111
|
+
}
|
|
112
|
+
else if (reason === 'clear') {
|
|
113
|
+
selectedValue = '';
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
selectedValue = (arrayChoices === null || arrayChoices === void 0 ? void 0 : arrayChoices.find((item) => item.id === '__null__'))
|
|
117
|
+
? '__null__'
|
|
118
|
+
: null;
|
|
119
|
+
}
|
|
120
|
+
setCurrentOption(option);
|
|
121
|
+
onChange({
|
|
122
|
+
target: {
|
|
123
|
+
name: name,
|
|
124
|
+
value: selectedValue,
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
}, [multiple, onChange, name, arrayChoices]);
|
|
128
|
+
const getOptionLabel = useCallback((value) => {
|
|
129
|
+
var _a, _b, _c, _d, _e, _f;
|
|
130
|
+
if (typeof value !== 'object') {
|
|
131
|
+
value = arrayChoices === null || arrayChoices === void 0 ? void 0 : arrayChoices.find((option) => option.id == value);
|
|
132
|
+
}
|
|
133
|
+
const isTranslation = (value === null || value === void 0 ? void 0 : value.label) &&
|
|
134
|
+
typeof value.label === 'object' &&
|
|
135
|
+
((_b = (_a = value.label) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.defaults) &&
|
|
136
|
+
typeof ((_d = (_c = value.label) === null || _c === void 0 ? void 0 : _c.props) === null || _d === void 0 ? void 0 : _d.defaults) === 'string';
|
|
137
|
+
if (isTranslation) {
|
|
138
|
+
const translatableText = (_f = (_e = value.label) === null || _e === void 0 ? void 0 : _e.props) === null || _f === void 0 ? void 0 : _f.defaults;
|
|
139
|
+
return t(translatableText);
|
|
140
|
+
}
|
|
141
|
+
return (value === null || value === void 0 ? void 0 : value.label) || '';
|
|
142
|
+
}, [arrayChoices, t]);
|
|
143
|
+
const isOptionEqualToValue = useCallback((option, value) => {
|
|
144
|
+
if (value === (currentOption === null || currentOption === void 0 ? void 0 : currentOption.id)) {
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
if ((option === null || option === void 0 ? void 0 : option.id) == value) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
if ((option === null || option === void 0 ? void 0 : option.id) == value.id) {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}, []);
|
|
155
|
+
const arrayChoicesLength = (_a = arrayChoices === null || arrayChoices === void 0 ? void 0 : arrayChoices.length) !== null && _a !== void 0 ? _a : 0;
|
|
156
|
+
const renderInput = useCallback((props) => {
|
|
157
|
+
const inputProps = Object.assign(Object.assign({}, props.InputProps), { notched: true });
|
|
158
|
+
const showPlaceholder = !searchTerm && !loading;
|
|
159
|
+
const inputPlaceholder = showPlaceholder
|
|
160
|
+
? t('Type to search')
|
|
161
|
+
: props.placeholder;
|
|
162
|
+
return (_jsx(StyledAutocompleteTextField, Object.assign({}, props, { name: name, label: label, required: required, disabled: disabled, InputProps: inputProps, InputLabelProps: { shrink: true, required: required }, error: error, errorMsg: errorMsg, helperText: helperText, placeholder: inputPlaceholder })));
|
|
163
|
+
}, [
|
|
164
|
+
name,
|
|
165
|
+
label,
|
|
166
|
+
required,
|
|
167
|
+
disabled,
|
|
168
|
+
error,
|
|
169
|
+
errorMsg,
|
|
170
|
+
helperText,
|
|
171
|
+
arrayChoicesLength,
|
|
172
|
+
searchTerm,
|
|
173
|
+
loading,
|
|
174
|
+
]);
|
|
175
|
+
const dropdownHelperText = 'Type to load more options';
|
|
176
|
+
const CustomOption = useCallback((props) => {
|
|
177
|
+
return (_jsxs(Paper, Object.assign({}, props, { children: [props.children, dropdownHelperText && (_jsxs(Box, Object.assign({ sx: {
|
|
178
|
+
p: 2,
|
|
179
|
+
borderTop: '1px solid',
|
|
180
|
+
borderColor: 'divider',
|
|
181
|
+
backgroundColor: 'var(--color-background)',
|
|
182
|
+
color: 'var(--color-text)',
|
|
183
|
+
display: 'flex',
|
|
184
|
+
alignItems: 'center',
|
|
185
|
+
gap: '4px',
|
|
186
|
+
} }, { children: [_jsx(SearchIcon, { sx: { fontSize: '18px' } }), _jsx(Typography, Object.assign({ variant: 'caption' }, { children: t(dropdownHelperText) }))] })))] })));
|
|
187
|
+
}, [dropdownHelperText]);
|
|
188
|
+
const disableClearable = arrayChoices.find((item) => item.id === '__null__')
|
|
189
|
+
? false
|
|
190
|
+
: true;
|
|
191
|
+
const safeValue = value.length !== '' ? value : null;
|
|
192
|
+
return (_jsx(MuiAutocomplete, { className: 'dynamic-autocomplete' + className, value: safeValue, multiple: multiple, disabled: disabled, disableClearable: disableClearable, onChange: onChangeWrapper, onBlur: onBlur, onInputChange: handleInputChange, onClose: () => setOpen(false), onOpen: () => setOpen(true), options: arrayChoices !== null && arrayChoices !== void 0 ? arrayChoices : [], getOptionLabel: getOptionLabel, isOptionEqualToValue: isOptionEqualToValue, loading: loading, placeholder: props.placeholder, renderInput: renderInput, PaperComponent: CustomOption, renderOption: (props, option) => (_jsx(Box, Object.assign({ component: 'li', className: 'autocomplete-option', "data-value": option.id }, props, { children: option.label }))) }));
|
|
193
|
+
};
|
|
194
|
+
export default DynamicAutocomplete;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const StyledDynamicAutocomplete: import("@emotion/styled").StyledComponent<import("./DynamicAutocomplete").DynamicAutocompleteProps & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { PropertySpec } from '../../../api';
|
|
3
|
+
import { ScalarEntityValue } from '../../../entity';
|
|
4
|
+
import { NullableFormFieldFactoryChoices } from '../FormFieldFactory';
|
|
5
|
+
import { SelectOptionsType } from 'entities/EntityInterface';
|
|
6
|
+
import { FormOnChangeEvent } from 'entities/DefaultEntityBehavior/Form/Form';
|
|
7
|
+
declare type DynamicAutocompleteFactoryPropsType = {
|
|
8
|
+
fld: string;
|
|
9
|
+
property: PropertySpec;
|
|
10
|
+
disabled: boolean;
|
|
11
|
+
multiSelect: boolean;
|
|
12
|
+
value: ScalarEntityValue | Array<ScalarEntityValue>;
|
|
13
|
+
hasChanged: boolean;
|
|
14
|
+
error: React.ReactNode;
|
|
15
|
+
touched: boolean | undefined;
|
|
16
|
+
changeHandler: (event: FormOnChangeEvent) => void;
|
|
17
|
+
choices: NullableFormFieldFactoryChoices;
|
|
18
|
+
handleBlur: (event: React.FocusEvent) => void;
|
|
19
|
+
selectOptions: (() => Promise<SelectOptionsType>) | undefined;
|
|
20
|
+
};
|
|
21
|
+
export declare const DynamicAutocompleteFactory: (props: DynamicAutocompleteFactoryPropsType) => JSX.Element;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { DynamicAutocomplete } from '../../Field/DynamicAutocomplete';
|
|
3
|
+
export const DynamicAutocompleteFactory = (props) => {
|
|
4
|
+
const { selectOptions, fld, disabled, multiSelect, value, hasChanged, error, touched, property, changeHandler, handleBlur, } = props;
|
|
5
|
+
return (_jsx(DynamicAutocomplete, { name: fld, label: property.label, value: value, multiple: multiSelect, nullOption: property.null, required: property.required, disabled: disabled, onBlur: handleBlur, error: touched && Boolean(error), errorMsg: touched && error, helperText: property.helpText, hasChanged: hasChanged, onChange: changeHandler, selectOptions: selectOptions }));
|
|
6
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DynamicAutocompleteFactory } from './DynamicAutocompleteFactory';
|
|
1
2
|
import { AutocompleteFactory } from './AutocompleteFactory';
|
|
2
3
|
import { DateFactory } from './DateFactory';
|
|
3
4
|
import { DateTimeFactory } from './DateTimeFactory';
|
|
@@ -11,4 +12,4 @@ import { SwitchFactory } from './SwitchFactory';
|
|
|
11
12
|
import { TextareaFactory } from './TextareaFactory';
|
|
12
13
|
import { TimeFactory } from './TimeFactory';
|
|
13
14
|
import { ColorFactory } from './ColorFactory';
|
|
14
|
-
export { AutocompleteFactory, DateFactory, DateTimeFactory, DropdownFactory, FileUploadFactory, InputTextFactory, MultilangFactory, NumberFactory, PasswordFactory, SwitchFactory, TextareaFactory, TimeFactory, ColorFactory, };
|
|
15
|
+
export { DynamicAutocompleteFactory, AutocompleteFactory, DateFactory, DateTimeFactory, DropdownFactory, FileUploadFactory, InputTextFactory, MultilangFactory, NumberFactory, PasswordFactory, SwitchFactory, TextareaFactory, TimeFactory, ColorFactory, };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DynamicAutocompleteFactory } from './DynamicAutocompleteFactory';
|
|
1
2
|
import { AutocompleteFactory } from './AutocompleteFactory';
|
|
2
3
|
import { DateFactory } from './DateFactory';
|
|
3
4
|
import { DateTimeFactory } from './DateTimeFactory';
|
|
@@ -11,4 +12,4 @@ import { SwitchFactory } from './SwitchFactory';
|
|
|
11
12
|
import { TextareaFactory } from './TextareaFactory';
|
|
12
13
|
import { TimeFactory } from './TimeFactory';
|
|
13
14
|
import { ColorFactory } from './ColorFactory';
|
|
14
|
-
export { AutocompleteFactory, DateFactory, DateTimeFactory, DropdownFactory, FileUploadFactory, InputTextFactory, MultilangFactory, NumberFactory, PasswordFactory, SwitchFactory, TextareaFactory, TimeFactory, ColorFactory, };
|
|
15
|
+
export { DynamicAutocompleteFactory, AutocompleteFactory, DateFactory, DateTimeFactory, DropdownFactory, FileUploadFactory, InputTextFactory, MultilangFactory, NumberFactory, PasswordFactory, SwitchFactory, TextareaFactory, TimeFactory, ColorFactory, };
|
|
@@ -12,6 +12,7 @@ export default class FormFieldFactory {
|
|
|
12
12
|
private handleBlur;
|
|
13
13
|
private divRef?;
|
|
14
14
|
constructor(entityService: EntityService, formik: useFormikType, changeHandler: (event: FormOnChangeEvent) => void, handleBlur: (event: React.FocusEvent) => void, divRef?: React.RefObject<HTMLDivElement> | undefined);
|
|
15
|
+
private getDynamicSelectOptions;
|
|
15
16
|
getFormField(fld: string, choices: NullableFormFieldFactoryChoices, readOnly?: boolean): JSX.Element | null;
|
|
16
17
|
createByPropertySpec(fld: string, property: PropertySpec, choices: NullableFormFieldFactoryChoices, readOnly?: boolean): JSX.Element | null;
|
|
17
18
|
getProperty(fld: string): PropertySpec | null;
|
|
@@ -3,7 +3,8 @@ import { InputAdornment, } from '@mui/material';
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { isPropertyEmbeddable, isPropertyFk, isPropertyScalar, } from '../../api/ParsedApiSpecInterface';
|
|
5
5
|
import { CustomFunctionComponentContext, } from '../../form/Field/CustomComponentWrapper';
|
|
6
|
-
import { AutocompleteFactory, DateFactory, DateTimeFactory, DropdownFactory, FileUploadFactory, InputTextFactory, MultilangFactory, NumberFactory, PasswordFactory, SwitchFactory, TextareaFactory, TimeFactory, ColorFactory, } from './Factory/index';
|
|
6
|
+
import { DynamicAutocompleteFactory, AutocompleteFactory, DateFactory, DateTimeFactory, DropdownFactory, FileUploadFactory, InputTextFactory, MultilangFactory, NumberFactory, PasswordFactory, SwitchFactory, TextareaFactory, TimeFactory, ColorFactory, } from './Factory/index';
|
|
7
|
+
import { StoreContainer } from '../../../store';
|
|
7
8
|
export default class FormFieldFactory {
|
|
8
9
|
constructor(entityService, formik, changeHandler, handleBlur, divRef) {
|
|
9
10
|
this.entityService = entityService;
|
|
@@ -12,6 +13,18 @@ export default class FormFieldFactory {
|
|
|
12
13
|
this.handleBlur = handleBlur;
|
|
13
14
|
this.divRef = divRef;
|
|
14
15
|
}
|
|
16
|
+
getDynamicSelectOptions(property) {
|
|
17
|
+
var _a;
|
|
18
|
+
if (!isPropertyFk(property)) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
const entities = StoreContainer.store.getState().entities.entities;
|
|
22
|
+
const entityName = property.$ref.replace('#/definitions/', '');
|
|
23
|
+
if (!((_a = entities[entityName]) === null || _a === void 0 ? void 0 : _a.dynamicSelectOptions)) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
return entities[entityName].selectOptions;
|
|
27
|
+
}
|
|
15
28
|
getFormField(fld, choices, readOnly = false) {
|
|
16
29
|
const property = this.getProperty(fld);
|
|
17
30
|
if (!property) {
|
|
@@ -34,6 +47,10 @@ export default class FormFieldFactory {
|
|
|
34
47
|
.component;
|
|
35
48
|
return (_jsx(PropertyComponent, { _context: CustomFunctionComponentContext.write, _columnName: fld, readOnly: readOnly, formik: this.formik, values: this.formik.values, choices: choices, property: property, disabled: disabled, changeHandler: this.changeHandler, onBlur: this.handleBlur, formFieldFactory: this }));
|
|
36
49
|
}
|
|
50
|
+
const dynamicSelectOptions = this.getDynamicSelectOptions(property);
|
|
51
|
+
if (dynamicSelectOptions) {
|
|
52
|
+
return (_jsx(DynamicAutocompleteFactory, { fld: fld, property: property, disabled: disabled, multiSelect: multiSelect, value: value, hasChanged: hasChanged, error: error, touched: touched, selectOptions: dynamicSelectOptions, choices: choices, changeHandler: this.changeHandler, handleBlur: this.handleBlur }));
|
|
53
|
+
}
|
|
37
54
|
if (isPropertyFk(property) || multiSelect) {
|
|
38
55
|
return (_jsx(AutocompleteFactory, { fld: fld, property: property, disabled: disabled, multiSelect: multiSelect, value: value, hasChanged: hasChanged, error: error, touched: touched, choices: choices, changeHandler: this.changeHandler, handleBlur: this.handleBlur }));
|
|
39
56
|
}
|
package/translations/ca.json
CHANGED
|
@@ -40,6 +40,8 @@
|
|
|
40
40
|
"Starts with": "empieza por",
|
|
41
41
|
"This change will affect": "Aquest canvi afectarà",
|
|
42
42
|
"True": "Verdadero",
|
|
43
|
+
"Type to load more options": "Escriu per carregar més opcions",
|
|
44
|
+
"Type to search": "Escriu per cercar",
|
|
43
45
|
"Upload image": "Subir imagen",
|
|
44
46
|
"Username": "Usuari",
|
|
45
47
|
"Validation error": "Error de validación",
|
package/translations/en.json
CHANGED
|
@@ -40,6 +40,8 @@
|
|
|
40
40
|
"Starts with": "Starts with",
|
|
41
41
|
"This change will affect": "This change will affect",
|
|
42
42
|
"True": "True",
|
|
43
|
+
"Type to load more options": "Type to load more options",
|
|
44
|
+
"Type to search": "Type to search",
|
|
43
45
|
"Upload image": "Upload image",
|
|
44
46
|
"Username": "Username",
|
|
45
47
|
"Validation error": "Validation error",
|
|
@@ -48,7 +50,7 @@
|
|
|
48
50
|
"Yes, delete it": "Yes, delete it",
|
|
49
51
|
"You are about to remove": "You are about to remove",
|
|
50
52
|
"You are about to update": "You are about to update",
|
|
51
|
-
"You haven
|
|
53
|
+
"You haven't created any {{entity}} yet.": "You haven't created any {{entity}} yet.",
|
|
52
54
|
"entities": "entities",
|
|
53
55
|
"invalid pattern": "invalid pattern",
|
|
54
56
|
"required value": "required value",
|
package/translations/es.json
CHANGED
|
@@ -40,6 +40,8 @@
|
|
|
40
40
|
"Starts with": "empieza por",
|
|
41
41
|
"This change will affect": "Este cambio afectará",
|
|
42
42
|
"True": "Verdadero",
|
|
43
|
+
"Type to load more options": "Escribe para cargar más opciones",
|
|
44
|
+
"Type to search": "Escribe para buscar",
|
|
43
45
|
"Upload image": "Subir imagen",
|
|
44
46
|
"Username": "Usuario",
|
|
45
47
|
"Validation error": "Error de validación",
|
|
@@ -48,7 +50,7 @@
|
|
|
48
50
|
"Yes, delete it": "Si, eliminar",
|
|
49
51
|
"You are about to remove": "Estás a punto de eliminar",
|
|
50
52
|
"You are about to update": "Estás a punto de actualizar",
|
|
51
|
-
"You haven
|
|
53
|
+
"You haven't created any {{entity}} yet.": "Aún no has creado ningún {{entity}}",
|
|
52
54
|
"entities": "entidades",
|
|
53
55
|
"invalid pattern": "Patrón invalido",
|
|
54
56
|
"required value": "valor requerido",
|
package/translations/it.json
CHANGED
|
@@ -40,6 +40,8 @@
|
|
|
40
40
|
"Starts with": "Starts with",
|
|
41
41
|
"This change will affect": "Questa modifica influirà",
|
|
42
42
|
"True": "True",
|
|
43
|
+
"Type to load more options": "Digita per caricare più opzioni",
|
|
44
|
+
"Type to search": "Digita per cercare",
|
|
43
45
|
"Upload image": "Upload image",
|
|
44
46
|
"Username": "Username",
|
|
45
47
|
"Validation error": "Validation error",
|