@entryscape/rdforms 10.5.2 → 10.6.2
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 +5 -5
- package/dist/rdforms.bootstrap.js +9 -9
- package/dist/rdforms.jquery.js +3 -3
- package/dist/rdforms.node.js +3 -3
- package/dist/rdforms.react.js +27 -27
- package/index.bmd.js +5 -4
- package/package.json +2 -1
- package/src/model/CODES.js +17 -0
- package/src/model/CardinalityTracker.js +2 -1
- package/src/model/ChoiceBinding.js +7 -1
- package/src/model/engine.js +1 -19
- package/src/model/validate.js +21 -20
- package/src/template/Item.js +46 -51
- package/src/view/Editor.js +8 -3
- package/src/view/Presenter.js +2 -1
- package/src/view/ValidationPresenter.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 +13 -8
- package/src/view/react/textEditors.js +5 -0
- package/src/view/renderingContext.js +2 -2
- package/src/view/resources/rdforms.css +1 -2
|
@@ -32,18 +32,21 @@ editors.itemtype('text').datatype('xsd:duration').register(durationEditor);
|
|
|
32
32
|
tb.set('value', '');
|
|
33
33
|
}; */
|
|
34
34
|
|
|
35
|
-
const addChangeListener = (inp, binding, regex, extLink) => {
|
|
35
|
+
const addChangeListener = (inp, binding, regex, extLink, help) => {
|
|
36
36
|
let to = null;
|
|
37
37
|
const s = () => {
|
|
38
38
|
to = null;
|
|
39
|
-
const val = inp.val();
|
|
39
|
+
const val = inp.val().trim();
|
|
40
40
|
let disableExtLink = true;
|
|
41
|
-
if (!regex || regex.test(val)) {
|
|
41
|
+
if (val === '' || !regex || regex.test(val)) {
|
|
42
42
|
binding.setGist(val);
|
|
43
43
|
if (extLink && val) {
|
|
44
44
|
extLink.prop('href', binding.getValue());
|
|
45
45
|
disableExtLink = false;
|
|
46
46
|
}
|
|
47
|
+
help.toggleClass('rdformsHelpActive', false);
|
|
48
|
+
} else {
|
|
49
|
+
help.toggleClass('rdformsHelpActive', true);
|
|
47
50
|
}
|
|
48
51
|
if (extLink) {
|
|
49
52
|
extLink.toggleClass('rdformsExtLinkDisabled', disableExtLink);
|
|
@@ -63,19 +66,27 @@ const registerPattern = (pattern, datatype) => {
|
|
|
63
66
|
const regex = new RegExp(pattern);
|
|
64
67
|
editors.itemtype('text').datatype(datatype)
|
|
65
68
|
.register((fieldDiv, binding, context) => {
|
|
66
|
-
const $input = jquery(
|
|
69
|
+
const $input = jquery(`<input type="text" class="form-control rdformsFieldInput"
|
|
70
|
+
placeholder="${binding.getItem().getPlaceholder() || ''}">`);
|
|
67
71
|
$input.val(binding.getGist())
|
|
68
72
|
.attr('pattern', pattern)
|
|
69
73
|
.appendTo(fieldDiv);
|
|
70
74
|
|
|
75
|
+
const help = binding.getItem().getHelp();
|
|
76
|
+
let $help;
|
|
77
|
+
if (help) {
|
|
78
|
+
$help = jquery(`<span class="rdformsHelp">${help}</span>`);
|
|
79
|
+
$help.appendTo(fieldDiv);
|
|
80
|
+
}
|
|
81
|
+
|
|
71
82
|
if (binding.getItem().hasStyle('externalLink')) {
|
|
72
83
|
const $extLink = jquery(`<a class="fas fa-external-link-alt rdformsExtLink ${renderingContext.getExtLinkClass()}" target="_blank">`);
|
|
73
84
|
$extLink.appendTo(context.controlDiv);
|
|
74
85
|
jquery(fieldDiv).addClass('rdformsExtLinkControl');
|
|
75
|
-
addChangeListener($input, binding, regex, $extLink);
|
|
86
|
+
addChangeListener($input, binding, regex, $extLink, $help);
|
|
76
87
|
$input.keyup();
|
|
77
88
|
} else {
|
|
78
|
-
addChangeListener($input, binding, regex);
|
|
89
|
+
addChangeListener($input, binding, regex, undefined, $help);
|
|
79
90
|
}
|
|
80
91
|
|
|
81
92
|
|
|
@@ -98,7 +109,7 @@ editors.itemtype('text').register((fieldDiv, binding, context) => {
|
|
|
98
109
|
let $input;
|
|
99
110
|
if (item.hasStyle('multiline')) {
|
|
100
111
|
const originalNrOfLines = countLines(binding.getGist());
|
|
101
|
-
$input = jquery(`<textarea class="form-control rdformsFieldInput autoExpand" rows="${originalNrOfLines}">`);
|
|
112
|
+
$input = jquery(`<textarea class="form-control rdformsFieldInput autoExpand" placeholder="${item.getPlaceholder() || ''}" rows="${originalNrOfLines}">`);
|
|
102
113
|
$input.on('input focus', function () {
|
|
103
114
|
if (this.baseScrollHeight === undefined) {
|
|
104
115
|
const originalHeight = $input.height();
|
|
@@ -110,13 +121,20 @@ editors.itemtype('text').register((fieldDiv, binding, context) => {
|
|
|
110
121
|
this.rows = rows;
|
|
111
122
|
});
|
|
112
123
|
} else if (item.hasStyle('email')) {
|
|
113
|
-
$input = jquery(
|
|
124
|
+
$input = jquery(`<input type="email" class="form-control rdformsFieldInput" placeholder="${item.getPlaceholder() || ''}">`);
|
|
114
125
|
} else {
|
|
115
|
-
$input = jquery(
|
|
126
|
+
$input = jquery(`<input type="text" class="form-control rdformsFieldInput" placeholder="${item.getPlaceholder() || ''}">`);
|
|
116
127
|
}
|
|
117
128
|
$input.val(binding.getGist())
|
|
118
129
|
.appendTo(fieldDiv);
|
|
119
130
|
|
|
131
|
+
const help = item.getHelp();
|
|
132
|
+
let $help;
|
|
133
|
+
if (help) {
|
|
134
|
+
$help = jquery(`<span class="rdformsHelp">${help}</span>`);
|
|
135
|
+
$help.appendTo(fieldDiv);
|
|
136
|
+
}
|
|
137
|
+
|
|
120
138
|
const pattern = item.getPattern();
|
|
121
139
|
let regex = null;
|
|
122
140
|
if (pattern != null) {
|
|
@@ -127,10 +145,10 @@ editors.itemtype('text').register((fieldDiv, binding, context) => {
|
|
|
127
145
|
const $extLink = jquery(`<a class="fas fa-external-link-alt rdformsExtLink ${renderingContext.getExtLinkClass()}" target="_blank">`);
|
|
128
146
|
$extLink.appendTo(context.controlDiv);
|
|
129
147
|
jquery(fieldDiv).addClass('rdformsExtLinkControl');
|
|
130
|
-
addChangeListener($input, binding, regex, $extLink);
|
|
148
|
+
addChangeListener($input, binding, regex, $extLink, $help);
|
|
131
149
|
$input.keyup();
|
|
132
150
|
} else {
|
|
133
|
-
addChangeListener($input, binding, regex);
|
|
151
|
+
addChangeListener($input, binding, regex, undefined, $help);
|
|
134
152
|
}
|
|
135
153
|
|
|
136
154
|
// If language control should be present
|
|
@@ -4,12 +4,20 @@ import './text';
|
|
|
4
4
|
import './choice';
|
|
5
5
|
import './table';
|
|
6
6
|
|
|
7
|
+
const createElement = (nodeStr, id) => {
|
|
8
|
+
const el = document.createElement(nodeStr);
|
|
9
|
+
if (id) {
|
|
10
|
+
el.id = id;
|
|
11
|
+
}
|
|
12
|
+
return el;
|
|
13
|
+
};
|
|
14
|
+
|
|
7
15
|
renderingContext.domQuery = (selector, node) => node.querySelector(selector);
|
|
8
16
|
|
|
9
|
-
renderingContext.domCreate = (nodeStr, parent) => parent.appendChild(
|
|
17
|
+
renderingContext.domCreate = (nodeStr, parent, id) => parent.appendChild(createElement(nodeStr, id));
|
|
10
18
|
|
|
11
|
-
renderingContext.domCreateAfter = (nodeStr, sibling) =>
|
|
12
|
-
sibling.parentNode.insertBefore(
|
|
19
|
+
renderingContext.domCreateAfter = (nodeStr, sibling, id) =>
|
|
20
|
+
sibling.parentNode.insertBefore(createElement(nodeStr, id), sibling.nextSibling);
|
|
13
21
|
|
|
14
22
|
renderingContext.domSetAttr = (node, attr, value) => {
|
|
15
23
|
if (value === '' || value === null) {
|
|
@@ -33,4 +41,4 @@ renderingContext.domClassToggle = (node, classStr, addOrRemove) => {
|
|
|
33
41
|
});
|
|
34
42
|
};
|
|
35
43
|
|
|
36
|
-
renderingContext.prePresenterViewRenderer = renderingContext.preEditorViewRenderer;
|
|
44
|
+
renderingContext.prePresenterViewRenderer = renderingContext.preEditorViewRenderer;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import jquery from 'jquery';
|
|
2
2
|
import renderingContext from '../renderingContext';
|
|
3
|
+
import Editor from '../Editor';
|
|
3
4
|
|
|
4
5
|
renderingContext.renderPresenterLabel = (rowNode, binding, item, context, labelRow) => {
|
|
5
|
-
let label = item.getLabel();
|
|
6
|
+
let label = context.view instanceof Editor ? item.getEditLabel() || item.getLabel() : item.getLabel();
|
|
6
7
|
if (label != null && label !== '') {
|
|
7
8
|
label = label.charAt(0).toUpperCase() + label.slice(1);
|
|
8
9
|
} else {
|
|
@@ -10,6 +11,9 @@ renderingContext.renderPresenterLabel = (rowNode, binding, item, context, labelR
|
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
const $labelDiv = jquery('<div class="rdformsLabel" tabindex="0">').text(label).appendTo(rowNode);
|
|
14
|
+
if (binding) {
|
|
15
|
+
$labelDiv.attr('id', context.view.createLabelIndex(binding));
|
|
16
|
+
}
|
|
13
17
|
if (labelRow) {
|
|
14
18
|
$labelDiv.addClass('rdformsLabelRow');
|
|
15
19
|
}
|
|
@@ -104,7 +104,7 @@ renderingContext.addCreateChildButton = (rowDiv, labelDiv, binding, context) =>
|
|
|
104
104
|
context.view.addRow(rowDiv, nBinding); // not the first binding...
|
|
105
105
|
}
|
|
106
106
|
};
|
|
107
|
-
let label = item.getLabel();
|
|
107
|
+
let label = item.getEditLabel() || item.getLabel();
|
|
108
108
|
if (label != null && label !== '') {
|
|
109
109
|
label = label.charAt(0).toUpperCase() + label.slice(1);
|
|
110
110
|
} else {
|
package/src/view/react/choice.js
CHANGED
|
@@ -3,20 +3,26 @@ import React, { useState, useEffect } from 'react';
|
|
|
3
3
|
import renderingContext from '../renderingContext';
|
|
4
4
|
import system from '../../model/system';
|
|
5
5
|
import utils from '../../utils';
|
|
6
|
+
import { Editor } from './Wrappers';
|
|
6
7
|
|
|
7
8
|
// -------------- Presenters ----------------
|
|
8
9
|
const presenters = renderingContext.presenterRegistry;
|
|
9
10
|
|
|
10
|
-
const choicify = func => (fieldDiv, binding) => {
|
|
11
|
+
const choicify = func => (fieldDiv, binding, context) => {
|
|
11
12
|
const choice = binding.getChoice();
|
|
13
|
+
const isEditor = context.view instanceof Editor;
|
|
12
14
|
let desc;
|
|
13
15
|
if (!choice) {
|
|
14
16
|
return;
|
|
15
17
|
}
|
|
16
|
-
|
|
18
|
+
|
|
19
|
+
if (isEditor && choice.editdescription) {
|
|
20
|
+
desc = utils.getLocalizedValue(choice.editdescription).value;
|
|
21
|
+
} else if (choice.description) {
|
|
17
22
|
desc = utils.getLocalizedValue(choice.description).value;
|
|
18
23
|
}
|
|
19
|
-
|
|
24
|
+
|
|
25
|
+
func(fieldDiv, binding, choice, desc, isEditor);
|
|
20
26
|
};
|
|
21
27
|
|
|
22
28
|
// Presenter for image.
|
|
@@ -34,13 +40,16 @@ presenters.itemtype('choice').style('stars').register(choicify(
|
|
|
34
40
|
}
|
|
35
41
|
}));
|
|
36
42
|
|
|
43
|
+
const getLocalizedLabel = (choice, isEditor) =>
|
|
44
|
+
utils.getLocalizedValue(isEditor ? choice.editlabel || choice.label : choice.label);
|
|
45
|
+
|
|
37
46
|
// Presenter for choices.
|
|
38
47
|
presenters.itemtype('choice').register(choicify(
|
|
39
|
-
(fieldDiv, binding, choice, desc) => {
|
|
48
|
+
(fieldDiv, binding, choice, desc, isEditor) => {
|
|
40
49
|
const item = binding.getItem();
|
|
41
50
|
const title = desc || choice.seeAlso || choice.value;
|
|
42
51
|
if ((item.hasStaticChoices() && !item.hasStyle('externalLink')) || item.hasStyle('noLink')) {
|
|
43
|
-
const locValue =
|
|
52
|
+
const locValue = getLocalizedLabel(choice, isEditor);
|
|
44
53
|
const langAttr = locValue.lang ? { lang: locValue.lang } : {};
|
|
45
54
|
fieldDiv.appendChild(<div key={binding.getHash()} {...langAttr} title={title} src={choice.value
|
|
46
55
|
}>{locValue.value}</div>);
|
|
@@ -55,11 +64,11 @@ presenters.itemtype('choice').register(choicify(
|
|
|
55
64
|
delete attrs.component;
|
|
56
65
|
|
|
57
66
|
fieldDiv.appendChild(React.createElement(() => {
|
|
58
|
-
const [locValue, setLocValue] = useState(
|
|
67
|
+
const [locValue, setLocValue] = useState(getLocalizedLabel(choice, isEditor));
|
|
59
68
|
useEffect(() => {
|
|
60
69
|
if (choice.load != null) {
|
|
61
70
|
choice.load(() => {
|
|
62
|
-
setLocValue(
|
|
71
|
+
setLocValue(getLocalizedLabel(choice, isEditor));
|
|
63
72
|
});
|
|
64
73
|
}
|
|
65
74
|
}, []);
|
|
@@ -25,7 +25,7 @@ export default function CheckBoxesEditor(props) {
|
|
|
25
25
|
const [resetCount, setResetCount] = React.useState(0);
|
|
26
26
|
const binding = props.binding;
|
|
27
27
|
const item = binding.getItem();
|
|
28
|
-
const choices = useLocalizedSortedChoices(binding);
|
|
28
|
+
const choices = useLocalizedSortedChoices(binding, true);
|
|
29
29
|
const choiceBindingPairs = useMemo(() => {
|
|
30
30
|
const parentBinding = binding.getParent();
|
|
31
31
|
const val2binding = {};
|
|
@@ -8,7 +8,7 @@ import ShowButton from './ShowButton';
|
|
|
8
8
|
|
|
9
9
|
export default (props) => {
|
|
10
10
|
const binding = props.binding;
|
|
11
|
-
const [choice, setChoice] = loadLocalizedChoice(binding);
|
|
11
|
+
const [choice, setChoice] = loadLocalizedChoice(binding, true);
|
|
12
12
|
const [error, setError] = useState(binding.getChoice()?.mismatch === true);
|
|
13
13
|
|
|
14
14
|
useEffect(() => {
|
|
@@ -44,6 +44,7 @@ export default (props) => {
|
|
|
44
44
|
disabled {...(choice && choice.mismatch ? { mismatch: true } : {})}
|
|
45
45
|
title={title}
|
|
46
46
|
value={label}
|
|
47
|
+
placeholder={binding.getItem().getPlaceholder()}
|
|
47
48
|
error={error}
|
|
48
49
|
variant={renderingContext.materialVariant}
|
|
49
50
|
/><ShowButton
|
|
@@ -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 { editLocalizedChoice, loadLocalizedChoice } 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] = loadLocalizedChoice(binding,
|
|
16
|
+
const [value, setValue] = loadLocalizedChoice(binding, true);
|
|
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,7 +4,8 @@ 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 {
|
|
7
|
+
import { Editor } from './Wrappers';
|
|
8
|
+
import CODES from '../../model/CODES';
|
|
8
9
|
|
|
9
10
|
const StyledTooltip = styled(
|
|
10
11
|
forwardRef(({ className, ...props }, ref) => (
|
|
@@ -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;
|