@entryscape/rdforms 10.5.2 → 10.6.0
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/dist/rdforms.bmd.js +4 -4
- package/dist/rdforms.bootstrap.js +7 -7
- package/dist/rdforms.jquery.js +3 -3
- package/dist/rdforms.node.js +3 -3
- package/dist/rdforms.react.js +23 -23
- package/index.bmd.js +5 -4
- package/package.json +1 -1
- package/src/model/ChoiceBinding.js +7 -1
- package/src/template/Item.js +46 -51
- package/src/view/Editor.js +4 -0
- package/src/view/Presenter.js +2 -1
- package/src/view/View.js +6 -3
- package/src/view/bootstrap/RadioButtonsEditor.js +4 -4
- package/src/view/bootstrap/choice.js +1 -1
- package/src/view/bootstrap/labels.js +12 -17
- package/src/view/bootstrap/style.css +11 -0
- package/src/view/bootstrap/table.js +5 -1
- package/src/view/bootstrap/text.js +29 -11
- package/src/view/jquery/components.js +12 -4
- package/src/view/jquery/labels.js +5 -1
- package/src/view/react/buttons.js +1 -1
- package/src/view/react/choice.js +16 -7
- package/src/view/react/choiceEditors/CheckBoxesEditor.js +1 -1
- package/src/view/react/choiceEditors/ChoiceLookup.js +2 -1
- package/src/view/react/choiceEditors/ChoiceLookupAndInlineSearch.js +6 -5
- package/src/view/react/choiceEditors/ChoiceSelector.js +2 -1
- package/src/view/react/choiceEditors/RadioButtonsEditor.js +2 -2
- package/src/view/react/components.js +6 -6
- package/src/view/react/date.js +0 -16
- package/src/view/react/hooks.js +17 -9
- package/src/view/react/labels.js +12 -7
- package/src/view/react/textEditors.js +5 -0
- package/src/view/renderingContext.js +2 -2
- package/src/view/resources/rdforms.css +1 -2
|
@@ -5,7 +5,7 @@ import Autocomplete from '@mui/material/Autocomplete';
|
|
|
5
5
|
import BuildIcon from '@mui/icons-material/Build';
|
|
6
6
|
import IconButton from '@mui/material/IconButton';
|
|
7
7
|
import renderingContext from '../../renderingContext';
|
|
8
|
-
import {
|
|
8
|
+
import { useLocalizedChoice, editLocalizedChoice } from '../hooks';
|
|
9
9
|
import ShowButton from './ShowButton';
|
|
10
10
|
|
|
11
11
|
let globalChoiceQueryThrottle;
|
|
@@ -13,7 +13,7 @@ let globalChoiceQueryThrottle;
|
|
|
13
13
|
export default (props) => {
|
|
14
14
|
const binding = props.binding;
|
|
15
15
|
const [options, setOptions] = useState([]);
|
|
16
|
-
const [value, setValue] =
|
|
16
|
+
const [value, setValue] = useLocalizedChoice(binding, options);
|
|
17
17
|
const [inputValue, setInputValue] = useState('');
|
|
18
18
|
const [open, setOpen] = useState(false);
|
|
19
19
|
const [error, setError] = useState(binding.getChoice()?.mismatch === true);
|
|
@@ -51,7 +51,7 @@ export default (props) => {
|
|
|
51
51
|
globalChoiceQueryThrottle = undefined;
|
|
52
52
|
props.context.chooser.search(binding.getItem(), inputValue.trimStart()).then((results) => {
|
|
53
53
|
if (active) {
|
|
54
|
-
setOptions(results.map(
|
|
54
|
+
setOptions(results.map(editLocalizedChoice));
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
57
|
}, 200);
|
|
@@ -71,6 +71,7 @@ export default (props) => {
|
|
|
71
71
|
aria-labelledby={labelledBy}
|
|
72
72
|
{...params}
|
|
73
73
|
{...(value && value.mismatch ? { error: true } : {})}
|
|
74
|
+
placeholder={binding.getItem().getPlaceholder()}
|
|
74
75
|
onKeyDown={({ key, keyCode }) => {
|
|
75
76
|
const isEnterKey = key === 'Enter' || keyCode === 13;
|
|
76
77
|
if (isEnterKey && !open) {
|
|
@@ -84,14 +85,14 @@ export default (props) => {
|
|
|
84
85
|
const showHandler = () => {
|
|
85
86
|
renderingContext.openChoiceSelector(props.binding, (selectedChoice) => {
|
|
86
87
|
binding.setChoice(selectedChoice);
|
|
87
|
-
setValue(
|
|
88
|
+
setValue(editLocalizedChoice(selectedChoice));
|
|
88
89
|
setError(selectedChoice.mismatch === true);
|
|
89
90
|
}, props.field);
|
|
90
91
|
};
|
|
91
92
|
|
|
92
93
|
const upgradeHandler = () => {
|
|
93
94
|
value.original.upgrade(props.binding, (upgradedChoice) => {
|
|
94
|
-
setValue(
|
|
95
|
+
setValue(editLocalizedChoice(upgradedChoice));
|
|
95
96
|
setError(upgradedChoice.mismatch === true);
|
|
96
97
|
});
|
|
97
98
|
};
|
|
@@ -15,7 +15,7 @@ import { useLocalizedSortedChoices, useLocalizedChoice } from '../hooks';
|
|
|
15
15
|
*/
|
|
16
16
|
export default (props) => {
|
|
17
17
|
const binding = props.binding;
|
|
18
|
-
const choices = useLocalizedSortedChoices(binding);
|
|
18
|
+
const choices = useLocalizedSortedChoices(binding, true);
|
|
19
19
|
const [value, setValue] = useLocalizedChoice(binding, choices);
|
|
20
20
|
const [error, setError] = useState(binding.getChoice()?.mismatch === true);
|
|
21
21
|
|
|
@@ -37,6 +37,7 @@ export default (props) => {
|
|
|
37
37
|
params.inputProps['aria-labelledby'] = labelledBy;
|
|
38
38
|
return (
|
|
39
39
|
<TextField
|
|
40
|
+
placeholder={binding.getItem().getPlaceholder()}
|
|
40
41
|
{...params}
|
|
41
42
|
{...(value && value.mismatch ? { error: true } : {})}
|
|
42
43
|
variant={renderingContext.materialVariant}
|
|
@@ -15,7 +15,7 @@ export default function RadioButtonsEditor(props) {
|
|
|
15
15
|
const binding = props.binding;
|
|
16
16
|
const item = binding.getItem();
|
|
17
17
|
const name = useName();
|
|
18
|
-
const choices = useLocalizedSortedChoices(binding);
|
|
18
|
+
const choices = useLocalizedSortedChoices(binding, true);
|
|
19
19
|
const [error, setError] = useState(binding.getChoice()?.mismatch === true);
|
|
20
20
|
const [value, setValue] = useState(() => {
|
|
21
21
|
const choice = binding.getChoice();
|
|
@@ -52,7 +52,7 @@ export default function RadioButtonsEditor(props) {
|
|
|
52
52
|
<RadioGroup
|
|
53
53
|
{...row}
|
|
54
54
|
key="radio"
|
|
55
|
-
aria-label={item.getLabel()}
|
|
55
|
+
aria-label={item.getEditLabel() || item.getLabel()}
|
|
56
56
|
name={name}
|
|
57
57
|
value={value}
|
|
58
58
|
onChange={handleChange}
|
|
@@ -83,7 +83,7 @@ let structId = 0;
|
|
|
83
83
|
* Note that all update of state variables are done by replacing the value (even for arrays and sets) to allow
|
|
84
84
|
* correct diffing of react.
|
|
85
85
|
*/
|
|
86
|
-
const newStruct = (Tag, parent) => {
|
|
86
|
+
const newStruct = (Tag, parent, nodeId) => {
|
|
87
87
|
const firstClsSet = new Set();
|
|
88
88
|
let firstChildArr = [];
|
|
89
89
|
let firstTextStr;
|
|
@@ -153,7 +153,7 @@ const newStruct = (Tag, parent) => {
|
|
|
153
153
|
};
|
|
154
154
|
// -- END
|
|
155
155
|
return (
|
|
156
|
-
<Tag className={clsSet.join(' ')}>
|
|
156
|
+
<Tag id={nodeId} className={clsSet.join(' ')}>
|
|
157
157
|
{childArr.map((child, index) => getReactComponent(child, index))}
|
|
158
158
|
{text}
|
|
159
159
|
</Tag>
|
|
@@ -166,15 +166,15 @@ const newStruct = (Tag, parent) => {
|
|
|
166
166
|
|
|
167
167
|
renderingContext.domQuery = (selector, struct) => struct.domQuery(selector);
|
|
168
168
|
|
|
169
|
-
renderingContext.domCreate = (nodeStr, parentStruct) => {
|
|
170
|
-
const struct = newStruct(nodeStr, parentStruct);
|
|
169
|
+
renderingContext.domCreate = (nodeStr, parentStruct, nodeId) => {
|
|
170
|
+
const struct = newStruct(nodeStr, parentStruct, nodeId);
|
|
171
171
|
parentStruct.appendChild(struct);
|
|
172
172
|
return struct;
|
|
173
173
|
};
|
|
174
174
|
|
|
175
|
-
renderingContext.domCreateAfter = (nodeStr, siblingStruct) => {
|
|
175
|
+
renderingContext.domCreateAfter = (nodeStr, siblingStruct, nodeId) => {
|
|
176
176
|
if (siblingStruct.parent) {
|
|
177
|
-
const struct = newStruct(nodeStr, siblingStruct.parent);
|
|
177
|
+
const struct = newStruct(nodeStr, siblingStruct.parent, nodeId);
|
|
178
178
|
siblingStruct.parent.appendAfter(struct, siblingStruct);
|
|
179
179
|
return struct;
|
|
180
180
|
}
|
package/src/view/react/date.js
CHANGED
|
@@ -140,14 +140,6 @@ const dateEditor = (fieldDiv, binding, context) => {
|
|
|
140
140
|
onChange={onDateChange}
|
|
141
141
|
autoOk={true}
|
|
142
142
|
mask={datePickerConfig.mask[selectedDatatype]}
|
|
143
|
-
PopperProps={{
|
|
144
|
-
modifiers: [
|
|
145
|
-
{
|
|
146
|
-
name: 'flip',
|
|
147
|
-
enabled: false,
|
|
148
|
-
},
|
|
149
|
-
],
|
|
150
|
-
}}
|
|
151
143
|
/>
|
|
152
144
|
)}
|
|
153
145
|
{(alternatives.DateTime || alternatives.Time) && (
|
|
@@ -162,14 +154,6 @@ const dateEditor = (fieldDiv, binding, context) => {
|
|
|
162
154
|
onChange={onDateChange}
|
|
163
155
|
ampm={false}
|
|
164
156
|
autoOk={true}
|
|
165
|
-
PopperProps={{
|
|
166
|
-
modifiers: [
|
|
167
|
-
{
|
|
168
|
-
name: 'flip',
|
|
169
|
-
enabled: false,
|
|
170
|
-
},
|
|
171
|
-
],
|
|
172
|
-
}}
|
|
173
157
|
/>
|
|
174
158
|
)}
|
|
175
159
|
{!onlyOneAlternative && (
|
package/src/view/react/hooks.js
CHANGED
|
@@ -3,18 +3,24 @@ import utils from '../../utils';
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Wraps a choice in an object where the current label, and description is localized.
|
|
6
|
+
*
|
|
6
7
|
* @param {Object} choice an original choice object with label and descriptions being maps with language strings
|
|
8
|
+
* @param {isEditor} true means we are in edit mode and editLabel or editDescription have preference if they exist.
|
|
7
9
|
* @return {Object}
|
|
8
10
|
*/
|
|
9
|
-
export const localizedChoice = choice => ({
|
|
11
|
+
export const localizedChoice = (choice, isEditor) => ({
|
|
10
12
|
value: choice.value,
|
|
11
|
-
label: utils.getLocalizedValue(choice.label).value,
|
|
12
|
-
description: choice.description
|
|
13
|
+
label: utils.getLocalizedValue(isEditor ? choice.editlabel || choice.label : choice.label).value,
|
|
14
|
+
description: choice.description || choice.editdescription ?
|
|
15
|
+
(utils.getLocalizedValue(isEditor ? choice.editdescription || choice.description : choice.description).value)
|
|
16
|
+
: undefined,
|
|
13
17
|
seeAlso: choice.seeAlso,
|
|
14
18
|
mismatch: choice.mismatch,
|
|
15
19
|
original: choice,
|
|
16
20
|
});
|
|
17
21
|
|
|
22
|
+
export const editLocalizedChoice = choice => localizedChoice(choice, true);
|
|
23
|
+
|
|
18
24
|
/**
|
|
19
25
|
* Use choices from a binding with localized labels and sorted.
|
|
20
26
|
* A copy is returned with precalculated labels to allow sorting, use the original property on each choice
|
|
@@ -24,9 +30,9 @@ export const localizedChoice = choice => ({
|
|
|
24
30
|
* @param {Binding} binding
|
|
25
31
|
* @return {Array}
|
|
26
32
|
*/
|
|
27
|
-
export const useLocalizedSortedChoices = binding => useMemo(() => {
|
|
33
|
+
export const useLocalizedSortedChoices = (binding, isEditor) => useMemo(() => {
|
|
28
34
|
const item = binding.getItem();
|
|
29
|
-
const choices = item.getChoices().map(localizedChoice);
|
|
35
|
+
const choices = item.getChoices().map(isEditor ? editLocalizedChoice : localizedChoice);
|
|
30
36
|
if (!item.hasStyle('preserveOrderOfChoices')) {
|
|
31
37
|
choices.sort((c1, c2) => (c1.label < c2.label ? -1 : 1));
|
|
32
38
|
}
|
|
@@ -56,18 +62,20 @@ export const useLocalizedChoice = (binding, choices) => useState(() => {
|
|
|
56
62
|
* Returns a localized choice, may trigger a load step to get a more fleshed out version of the choice,
|
|
57
63
|
* i.e. with label, description and seeAlso.
|
|
58
64
|
* @param {Binding} binding
|
|
65
|
+
* @param {boolean} isEditor if true any editlabel or editdescription takes precedence
|
|
59
66
|
*/
|
|
60
|
-
export const loadLocalizedChoice = (binding) => {
|
|
67
|
+
export const loadLocalizedChoice = (binding, isEditor) => {
|
|
68
|
+
const localize = isEditor ? editLocalizedChoice : localizedChoice;
|
|
61
69
|
const [choice, setChoice] = useState(() => {
|
|
62
70
|
const originalChoice = binding.getChoice() || null;
|
|
63
|
-
return originalChoice ?
|
|
71
|
+
return originalChoice ? localize(originalChoice) : null;
|
|
64
72
|
});
|
|
65
73
|
useEffect(() => {
|
|
66
74
|
if (choice && choice.original.load) {
|
|
67
75
|
choice.original.load(() => {
|
|
68
|
-
setChoice(
|
|
76
|
+
setChoice(localize(choice.original));
|
|
69
77
|
}, () => {
|
|
70
|
-
setChoice(
|
|
78
|
+
setChoice(localize(choice.original));
|
|
71
79
|
});
|
|
72
80
|
}
|
|
73
81
|
}, []);
|
package/src/view/react/labels.js
CHANGED
|
@@ -4,6 +4,7 @@ import Tooltip, { tooltipClasses } from '@mui/material/Tooltip';
|
|
|
4
4
|
import { styled } from '@mui/material/styles';
|
|
5
5
|
import ClickAwayListener from '@mui/material/ClickAwayListener';
|
|
6
6
|
import renderingContext from '../renderingContext';
|
|
7
|
+
import { Editor } from './Wrappers';
|
|
7
8
|
import { CODES } from '../../model/engine';
|
|
8
9
|
|
|
9
10
|
const StyledTooltip = styled(
|
|
@@ -37,7 +38,9 @@ const ItemTooltip = (props) => {
|
|
|
37
38
|
if (property) {
|
|
38
39
|
propinfo = <div className="rdformsProperty"><a target="_blank" href={property}>{property}</a></div>;
|
|
39
40
|
}
|
|
40
|
-
const description = props.
|
|
41
|
+
const description = props.context.view instanceof Editor ?
|
|
42
|
+
props.item.getEditDescription() || props.item.getDescription() : props.item.getDescription()
|
|
43
|
+
|| (property ? '' : props.context.view.messages.info_missing || '');
|
|
41
44
|
|
|
42
45
|
return (
|
|
43
46
|
<ClickAwayListener onClickAway={handleTooltipClose}>
|
|
@@ -64,24 +67,26 @@ const ItemTooltip = (props) => {
|
|
|
64
67
|
};
|
|
65
68
|
|
|
66
69
|
renderingContext.renderPresenterLabel = (rowNode, binding, item, context) => {
|
|
67
|
-
let label =
|
|
70
|
+
let label = context.view instanceof Editor ?
|
|
71
|
+
item.getEditLabel() || item.getLabel() : item.getLabel();
|
|
68
72
|
if (label != null && label !== '') {
|
|
69
73
|
label = label.charAt(0).toUpperCase() + label.slice(1);
|
|
70
74
|
} else {
|
|
71
75
|
label = '';
|
|
72
76
|
}
|
|
77
|
+
const labelId = binding ? context.view.createLabelIndex(binding) : undefined;
|
|
73
78
|
label = item.hasStyle('heading') ?
|
|
74
|
-
<h2 tabIndex="0" className="rdformsLabelRow"><span className="rdformsLabel">{label}</span></h2> :
|
|
75
|
-
<span tabIndex="0" className="rdformsLabelRow"><span className="rdformsLabel">{label}</span></span>;
|
|
76
|
-
rowNode.appendChild(<ItemTooltip key={`${binding ? binding.getHash() : item._internalId}_label` }
|
|
77
|
-
|
|
79
|
+
<h2 tabIndex="0" id={labelId} className="rdformsLabelRow"><span className="rdformsLabel">{label}</span></h2> :
|
|
80
|
+
<span tabIndex="0" id={labelId} className="rdformsLabelRow"><span className="rdformsLabel">{label}</span></span>;
|
|
81
|
+
rowNode.appendChild(<ItemTooltip key={`${binding ? binding.getHash() : item._internalId}_label` }
|
|
82
|
+
context={context} item={item}>{label}</ItemTooltip>);
|
|
78
83
|
};
|
|
79
84
|
|
|
80
85
|
renderingContext.renderEditorLabel = (rowNode, binding, item, context) => {
|
|
81
86
|
if (item.hasStyle('nonEditable') || item.hasStyle('heading')) {
|
|
82
87
|
renderingContext.renderPresenterLabel(rowNode, binding, item, context, true);
|
|
83
88
|
} else {
|
|
84
|
-
let label = item.getLabel();
|
|
89
|
+
let label = item.getEditLabel() || item.getLabel();
|
|
85
90
|
if (label != null && label !== '') {
|
|
86
91
|
label = label.charAt(0).toUpperCase() + label.slice(1);
|
|
87
92
|
} else {
|
|
@@ -93,7 +93,9 @@ editors.itemtype('text').register((fieldDiv, binding, context) => {
|
|
|
93
93
|
return <><TextField
|
|
94
94
|
className={extLink || langlit ? 'rdformsTwoThirds' : ''}
|
|
95
95
|
multiline={multiline}
|
|
96
|
+
placeholder={item.getPlaceholder()}
|
|
96
97
|
error={!valid}
|
|
98
|
+
helperText={!valid ? item.getHelp() || '' : ''}
|
|
97
99
|
variant={renderingContext.materialVariant} inputProps={iprops}
|
|
98
100
|
/>{extLink && (value != null || value === '') &&
|
|
99
101
|
(<IconButton aria-label={bundle.openLinkExternally} disabled={!valid} target='_blank' href={value}
|
|
@@ -107,6 +109,7 @@ editors.itemtype('text').register((fieldDiv, binding, context) => {
|
|
|
107
109
|
|
|
108
110
|
const bindToPattern = pattern => (fieldDiv, binding, context) => {
|
|
109
111
|
const regex = pattern ? new RegExp(pattern) : null;
|
|
112
|
+
const item = binding.getItem();
|
|
110
113
|
|
|
111
114
|
const TextComp = () => {
|
|
112
115
|
const [gist, setGist] = useState(binding.getGist());
|
|
@@ -131,6 +134,8 @@ const bindToPattern = pattern => (fieldDiv, binding, context) => {
|
|
|
131
134
|
};
|
|
132
135
|
return <TextField
|
|
133
136
|
error={!valid}
|
|
137
|
+
placeholder={item.getPlaceholder()}
|
|
138
|
+
helperText={!valid ? item.getHelp() || '' : ''}
|
|
134
139
|
variant={renderingContext.materialVariant} inputProps={iprops}
|
|
135
140
|
/>;
|
|
136
141
|
};
|
|
@@ -58,9 +58,9 @@ const defaultLanguages = [
|
|
|
58
58
|
const renderingContext = {
|
|
59
59
|
domQuery(/* selector, node */) {
|
|
60
60
|
},
|
|
61
|
-
domCreate(/* domStr, node */) {
|
|
61
|
+
domCreate(/* domStr, node, id */) {
|
|
62
62
|
},
|
|
63
|
-
domCreateAfter(/* domStr, node */) {
|
|
63
|
+
domCreateAfter(/* domStr, node, id */) {
|
|
64
64
|
},
|
|
65
65
|
domClassToggle(/* node, classStr, addOrRemove */) {
|
|
66
66
|
},
|
|
@@ -314,7 +314,7 @@ a.rdformsUrl:hover {
|
|
|
314
314
|
padding-right: 55px;
|
|
315
315
|
position: relative;
|
|
316
316
|
}
|
|
317
|
-
|
|
317
|
+
|
|
318
318
|
.rdformsEditor .rdformsField .rdformsChoiceLabel {
|
|
319
319
|
margin-left: 0.2em;
|
|
320
320
|
margin-right: 1em;
|
|
@@ -475,7 +475,6 @@ a.rdformsUrl:hover {
|
|
|
475
475
|
|
|
476
476
|
.compact .rdformsRow.rdformsTopLevel {
|
|
477
477
|
display: table;
|
|
478
|
-
width: 98%;
|
|
479
478
|
}
|
|
480
479
|
.compact .rdformsRow.rdformsTopLevel>div {
|
|
481
480
|
display: table-cell;
|