@luomus/laji-form 15.1.12 → 15.1.14
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/laji-form.js +1 -1
- package/lib/components/fields/ImageArrayField.d.ts +1 -0
- package/lib/components/fields/ImageArrayField.js +5 -2
- package/lib/components/fields/MapArrayField.js +20 -0
- package/lib/components/fields/MultiTagArrayField.js +1 -1
- package/lib/components/fields/SingleActiveArrayField.js +7 -12
- package/lib/components/fields/TagArrayField.d.ts +7 -1
- package/lib/components/fields/TagArrayField.js +20 -7
- package/lib/themes/bs5.js +7 -1
- package/lib/translations.json +17 -12
- package/package.json +1 -1
|
@@ -102,6 +102,7 @@ export declare function MediaArrayField<LFC extends Constructor<React.Component<
|
|
|
102
102
|
}) => void;
|
|
103
103
|
getMetadataPromise: () => Promise<MediaMetadataSchema>;
|
|
104
104
|
getMaxFileSizeAsString: () => string;
|
|
105
|
+
getAllowedMediaFormatsTranslationKey: () => "AllowedFileFormat" | "AllowedFileFormats";
|
|
105
106
|
getAllowedMediaFormatsAsString: () => string;
|
|
106
107
|
context: any;
|
|
107
108
|
setState<K extends keyof MediaArrayState>(state: MediaArrayState | ((prevState: Readonly<MediaArrayState>, props: Readonly<FieldProps>) => MediaArrayState | Pick<MediaArrayState, K> | null) | Pick<MediaArrayState, K> | null, callback?: (() => void) | undefined): void;
|
|
@@ -421,6 +421,9 @@ function MediaArrayField(ComposedComponent) {
|
|
|
421
421
|
let maxSize = this.MAX_FILE_SIZE.toString().substring(0, this.MAX_FILE_SIZE.toString().length - 6);
|
|
422
422
|
return maxSize + " " + `${this.props.formContext.translations.Mb}`;
|
|
423
423
|
};
|
|
424
|
+
this.getAllowedMediaFormatsTranslationKey = () => {
|
|
425
|
+
return this.ALLOWED_FILE_TYPES.length === 1 ? "AllowedFileFormat" : "AllowedFileFormats";
|
|
426
|
+
};
|
|
424
427
|
this.getAllowedMediaFormatsAsString = () => {
|
|
425
428
|
let formats = "";
|
|
426
429
|
for (let i = 0; i < this.ALLOWED_FILE_TYPES.length; i++) {
|
|
@@ -492,7 +495,7 @@ function MediaArrayField(ComposedComponent) {
|
|
|
492
495
|
translations.DropOrSelectFiles,
|
|
493
496
|
". "),
|
|
494
497
|
React.createElement("span", null,
|
|
495
|
-
translations.
|
|
498
|
+
translations[this.getAllowedMediaFormatsTranslationKey()],
|
|
496
499
|
" ",
|
|
497
500
|
this.getAllowedMediaFormatsAsString(),
|
|
498
501
|
" ",
|
|
@@ -561,7 +564,7 @@ function MediaArrayField(ComposedComponent) {
|
|
|
561
564
|
return body;
|
|
562
565
|
}, new FormData());
|
|
563
566
|
if (noValidData && invalidFile) {
|
|
564
|
-
fail(
|
|
567
|
+
fail(this.getAllowedMediaFormatsTranslationKey(), this.getAllowedMediaFormatsAsString() + ".");
|
|
565
568
|
return;
|
|
566
569
|
}
|
|
567
570
|
else if (noValidData && fileTooLarge) {
|
|
@@ -35,6 +35,7 @@ const NestField_1 = require("./NestField");
|
|
|
35
35
|
const ArrayFieldTemplate_1 = require("../templates/ArrayFieldTemplate");
|
|
36
36
|
const ArrayField_1 = require("./ArrayField");
|
|
37
37
|
const utils_3 = require("@rjsf/utils");
|
|
38
|
+
const utils_4 = require("@luomus/laji-map/lib/utils");
|
|
38
39
|
function parseGeometries(geometry) {
|
|
39
40
|
return ((geometry && geometry.type === "GeometryCollection") ? geometry.geometries : [geometry])
|
|
40
41
|
.filter(geometry => geometry)
|
|
@@ -594,6 +595,7 @@ let LineTransectMapArrayField = class LineTransectMapArrayField extends React.Co
|
|
|
594
595
|
});
|
|
595
596
|
const afterState = () => {
|
|
596
597
|
if (formDataChanged) {
|
|
598
|
+
formData = syncLineTransectStartEnd(formData);
|
|
597
599
|
this.props.onChange(addOrDelete ? ArrayField_1.onArrayFieldChange(formData, this.props) : formData);
|
|
598
600
|
}
|
|
599
601
|
if ("activeIdx" in state) {
|
|
@@ -635,6 +637,7 @@ let LineTransectMapArrayField = class LineTransectMapArrayField extends React.Co
|
|
|
635
637
|
});
|
|
636
638
|
};
|
|
637
639
|
this.state = { showLTTools: false };
|
|
640
|
+
this.props.onChange(syncLineTransectStartEnd(this.props.formData));
|
|
638
641
|
}
|
|
639
642
|
getOptions() {
|
|
640
643
|
const { formData, disabled, readonly } = this.props;
|
|
@@ -1781,3 +1784,20 @@ const getFeatureStyleWithHighlight = style => {
|
|
|
1781
1784
|
return Object.assign(Object.assign({}, style), { color, fillOpacity: saneOpacityRange(style.fillOpacity || 0.4 + 0.4) });
|
|
1782
1785
|
};
|
|
1783
1786
|
exports.getFeatureStyleWithHighlight = getFeatureStyleWithHighlight;
|
|
1787
|
+
const syncLineTransectStartEnd = (formData) => {
|
|
1788
|
+
const lineTransectFeature = Object.keys((formData || [])[0].geometry || {}).length
|
|
1789
|
+
? { type: "Feature", properties: {}, geometry: { type: "MultiLineString", coordinates: formData.map(item => item.geometry.coordinates) } }
|
|
1790
|
+
: undefined;
|
|
1791
|
+
if (lineTransectFeature) {
|
|
1792
|
+
return formData.map((item, idx) => {
|
|
1793
|
+
const [start, end] = utils_4.getLineTransectStartEndDistancesForIdx(lineTransectFeature, idx, 10);
|
|
1794
|
+
if (!item.gatheringFact) {
|
|
1795
|
+
item.gatheringFact = {};
|
|
1796
|
+
}
|
|
1797
|
+
item.gatheringFact.lineTransectSegmentMetersStart = start;
|
|
1798
|
+
item.gatheringFact.lineTransectSegmentMetersEnd = end;
|
|
1799
|
+
return Object.assign(Object.assign({}, item), { gatheringFact: Object.assign(Object.assign({}, (item.gatheringFact || {})), { lineTransectSegmentMetersStart: start, lineTransectSegmentMetersEnd: end }) });
|
|
1800
|
+
});
|
|
1801
|
+
}
|
|
1802
|
+
return formData;
|
|
1803
|
+
};
|
|
@@ -51,11 +51,11 @@ let MultiTagArrayField = class MultiTagArrayField extends React.Component {
|
|
|
51
51
|
}
|
|
52
52
|
});
|
|
53
53
|
this.onTagClick = memoize((fromField) => (idx, e) => {
|
|
54
|
-
e.preventDefault();
|
|
55
54
|
const { activeButtonIdx } = this.state;
|
|
56
55
|
if (activeButtonIdx === undefined) {
|
|
57
56
|
return;
|
|
58
57
|
}
|
|
58
|
+
e.preventDefault();
|
|
59
59
|
const { buttons = [] } = utils_1.getUiOptions(this.props.uiSchema);
|
|
60
60
|
const options = buttons[activeButtonIdx];
|
|
61
61
|
const { operation } = options;
|
|
@@ -29,8 +29,7 @@ const ArrayField_1 = require("./ArrayField");
|
|
|
29
29
|
const Context_1 = require("../../Context");
|
|
30
30
|
const ReactContext_1 = require("../../ReactContext");
|
|
31
31
|
const BaseComponent_1 = require("../BaseComponent");
|
|
32
|
-
const utils_3 = require("@
|
|
33
|
-
const utils_4 = require("@rjsf/utils");
|
|
32
|
+
const utils_3 = require("@rjsf/utils");
|
|
34
33
|
const memoize = require("memoizee");
|
|
35
34
|
const ArrayField_2 = require("./ArrayField");
|
|
36
35
|
const popupMappers = {
|
|
@@ -504,8 +503,8 @@ let UncontrolledArrayFieldTemplate = class UncontrolledArrayFieldTemplate extend
|
|
|
504
503
|
const that = this.props.formContext.this;
|
|
505
504
|
const arrayTemplateFieldProps = this.props;
|
|
506
505
|
const activeIdx = that.state.activeIdx;
|
|
507
|
-
const TitleFieldTemplate =
|
|
508
|
-
const DescriptionFieldTemplate =
|
|
506
|
+
const TitleFieldTemplate = utils_3.getTemplate("TitleFieldTemplate", this.props.registry, utils_1.getUiOptions(this.props.uiSchema));
|
|
507
|
+
const DescriptionFieldTemplate = utils_3.getTemplate("DescriptionFieldTemplate", this.props.registry, utils_1.getUiOptions(this.props.uiSchema));
|
|
509
508
|
const { Label } = this.props.formContext;
|
|
510
509
|
const Title = utils_1.getUiOptions(that.props.uiSchema).renderTitleAsLabel ? Label : TitleFieldTemplate;
|
|
511
510
|
const title = utils_1.getTitle(this.props, activeIdx);
|
|
@@ -700,8 +699,8 @@ let TableArrayFieldTemplate = class TableArrayFieldTemplate extends React.Compon
|
|
|
700
699
|
return React.createElement(ArrayFieldTemplate_1.default, Object.assign({}, this.props));
|
|
701
700
|
}
|
|
702
701
|
const { schema, uiSchema = {}, formData = [], items, disabled, readonly } = this.props;
|
|
703
|
-
const TitleFieldTemplate =
|
|
704
|
-
const DescriptionFieldTemplate =
|
|
702
|
+
const TitleFieldTemplate = utils_3.getTemplate("TitleFieldTemplate", this.props.registry, utils_1.getUiOptions(uiSchema));
|
|
703
|
+
const DescriptionFieldTemplate = utils_3.getTemplate("DescriptionFieldTemplate", this.props.registry, utils_1.getUiOptions(uiSchema));
|
|
705
704
|
const { renderTitleAsLabel, formatters = {}, shownColumns = [], removable = true } = utils_1.getUiOptions(uiSchema);
|
|
706
705
|
const { Label } = this.props.formContext;
|
|
707
706
|
const Title = renderTitleAsLabel ? Label : TitleFieldTemplate;
|
|
@@ -874,12 +873,8 @@ const headerFormatters = {
|
|
|
874
873
|
},
|
|
875
874
|
lineTransect: {
|
|
876
875
|
component: (props) => {
|
|
877
|
-
|
|
878
|
-
const
|
|
879
|
-
? { type: "Feature", properties: {}, geometry: { type: "MultiLineString", coordinates: props.that.props.formData.map(item => item.geometry.coordinates) } }
|
|
880
|
-
: undefined;
|
|
881
|
-
if (lineTransectFeature)
|
|
882
|
-
[start, end] = utils_3.getLineTransectStartEndDistancesForIdx(lineTransectFeature, props.idx, 10);
|
|
876
|
+
const item = props.that.props.formData[props.idx];
|
|
877
|
+
const [start, end] = [item.gatheringFact.lineTransectSegmentMetersStart, item.gatheringFact.lineTransectSegmentMetersEnd];
|
|
883
878
|
return props.idx !== undefined && end ? React.createElement("span", { className: "text-muted" }, `${start}-${end}m`) : null;
|
|
884
879
|
}
|
|
885
880
|
},
|
|
@@ -4,6 +4,12 @@ export default class TagArrayField extends React.Component<any, any, any> {
|
|
|
4
4
|
"ui:options": PropTypes.Requireable<PropTypes.InferProps<{
|
|
5
5
|
separatorKeys: PropTypes.Requireable<(string | null | undefined)[]>;
|
|
6
6
|
showDeleteButton: PropTypes.Requireable<boolean>;
|
|
7
|
+
showAsLink: PropTypes.Requireable<boolean>;
|
|
8
|
+
linkPrefix: PropTypes.Requireable<string>;
|
|
9
|
+
replacements: PropTypes.Requireable<(PropTypes.InferProps<{
|
|
10
|
+
searchRegexp: PropTypes.Validator<string>;
|
|
11
|
+
replaceValue: PropTypes.Validator<string>;
|
|
12
|
+
}> | null | undefined)[]>;
|
|
7
13
|
}>>;
|
|
8
14
|
}>>;
|
|
9
15
|
schema: PropTypes.Validator<PropTypes.InferProps<{
|
|
@@ -31,7 +37,7 @@ export class TagInputComponent extends React.Component<any, any, any> {
|
|
|
31
37
|
onClick: () => void;
|
|
32
38
|
onInputChange: (e: any) => void;
|
|
33
39
|
onTagClick: ((idx: any) => (e: any) => void) & memoize.Memoized<(idx: any) => (e: any) => void>;
|
|
34
|
-
|
|
40
|
+
processValue(value: any): any;
|
|
35
41
|
}
|
|
36
42
|
import * as React from "react";
|
|
37
43
|
import * as PropTypes from "prop-types";
|
|
@@ -25,7 +25,13 @@ TagArrayField.propTypes = {
|
|
|
25
25
|
uiSchema: PropTypes.shape({
|
|
26
26
|
"ui:options": PropTypes.shape({
|
|
27
27
|
separatorKeys: PropTypes.arrayOf(PropTypes.string),
|
|
28
|
-
showDeleteButton: PropTypes.bool
|
|
28
|
+
showDeleteButton: PropTypes.bool,
|
|
29
|
+
showAsLink: PropTypes.bool,
|
|
30
|
+
linkPrefix: PropTypes.string,
|
|
31
|
+
replacements: PropTypes.arrayOf(PropTypes.shape({
|
|
32
|
+
searchRegexp: PropTypes.string.isRequired,
|
|
33
|
+
replaceValue: PropTypes.string.isRequired
|
|
34
|
+
}))
|
|
29
35
|
})
|
|
30
36
|
}),
|
|
31
37
|
schema: PropTypes.shape({
|
|
@@ -48,7 +54,7 @@ class TagInputComponent extends React.Component {
|
|
|
48
54
|
return separatorKeys;
|
|
49
55
|
};
|
|
50
56
|
this.onKeyDown = (e) => {
|
|
51
|
-
const value = this.
|
|
57
|
+
const value = this.processValue(this.state.value);
|
|
52
58
|
const { tags = [] } = this.props;
|
|
53
59
|
const separatorKeys = this.getSeparatorKeys(this.props.uiSchema);
|
|
54
60
|
if (separatorKeys.includes(e.key) && !utils_1.isEmptyString(value)) {
|
|
@@ -74,7 +80,7 @@ class TagInputComponent extends React.Component {
|
|
|
74
80
|
this.onBlur = (e) => {
|
|
75
81
|
this.setState({ focused: false });
|
|
76
82
|
utils_1.triggerParentComponent("onBlur", e, this.props);
|
|
77
|
-
const value = this.
|
|
83
|
+
const value = this.processValue(this.state.value);
|
|
78
84
|
if (!utils_1.isEmptyString(value)) {
|
|
79
85
|
this.props.onChange([...(this.props.tags || []), value], "blur");
|
|
80
86
|
}
|
|
@@ -90,7 +96,7 @@ class TagInputComponent extends React.Component {
|
|
|
90
96
|
onInputChange && e.persist();
|
|
91
97
|
const { target: { value } } = e;
|
|
92
98
|
const separatorKeys = this.getSeparatorKeys(this.props.uiSchema);
|
|
93
|
-
const splitted = separatorKeys.reduce((splitted, separator) => splitted.reduce((_splitted, i) => ([..._splitted, ...i.split(separator)]), []), [value]).map(s =>
|
|
99
|
+
const splitted = separatorKeys.reduce((splitted, separator) => splitted.reduce((_splitted, i) => ([..._splitted, ...i.split(separator)]), []), [value]).map(s => this.processValue(s)).filter(s => !utils_1.isEmptyString(s));
|
|
94
100
|
this.setState({ value }, () => {
|
|
95
101
|
onInputChange && this.props.onInputChange(e);
|
|
96
102
|
if (splitted.length > 1) {
|
|
@@ -107,9 +113,16 @@ class TagInputComponent extends React.Component {
|
|
|
107
113
|
UNSAFE_componentWillReceiveProps(props) {
|
|
108
114
|
this.setState(this.getStateFromProps(props));
|
|
109
115
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
processValue(value) {
|
|
117
|
+
if (!value) {
|
|
118
|
+
return value;
|
|
119
|
+
}
|
|
120
|
+
value = value.trim();
|
|
121
|
+
const { replacements = [] } = utils_1.getUiOptions(this.props.uiSchema);
|
|
122
|
+
replacements.forEach(replacement => {
|
|
123
|
+
value = value.replace(new RegExp(replacement.searchRegexp), replacement.replaceValue);
|
|
124
|
+
});
|
|
125
|
+
return value;
|
|
113
126
|
}
|
|
114
127
|
render() {
|
|
115
128
|
let { tags = [], InputComponent, readonly, disabled, uiSchema } = this.props;
|
package/lib/themes/bs5.js
CHANGED
|
@@ -62,6 +62,12 @@ _Dropdown.Toggle = React.forwardRef((_a, ref) => {
|
|
|
62
62
|
var { variant } = _a, props = __rest(_a, ["variant"]);
|
|
63
63
|
return (React.createElement(react_bootstrap_5_1.Dropdown.Toggle, Object.assign({ variant: mapVariant(variant) }, props, { ref: ref })));
|
|
64
64
|
});
|
|
65
|
+
const _Popover = React.forwardRef((_a, ref) => {
|
|
66
|
+
var { children } = _a, props = __rest(_a, ["children"]);
|
|
67
|
+
return (React.createElement(react_bootstrap_5_1.Popover, Object.assign({}, props, { ref: ref }),
|
|
68
|
+
props.title ? React.createElement(react_bootstrap_5_1.Popover.Header, null, props.title) : null,
|
|
69
|
+
React.createElement(react_bootstrap_5_1.Popover.Body, null, children)));
|
|
70
|
+
});
|
|
65
71
|
const theme = {
|
|
66
72
|
Panel,
|
|
67
73
|
Table: react_bootstrap_5_1.Table,
|
|
@@ -74,7 +80,7 @@ const theme = {
|
|
|
74
80
|
ButtonToolbar: react_bootstrap_5_1.ButtonToolbar,
|
|
75
81
|
Overlay: React.forwardRef((props, ref) => React.createElement(react_bootstrap_5_1.Overlay, Object.assign({}, props, { ref: ref }))),
|
|
76
82
|
OverlayTrigger: (props) => React.createElement(react_bootstrap_5_1.OverlayTrigger, Object.assign({}, props)),
|
|
77
|
-
Popover:
|
|
83
|
+
Popover: _Popover,
|
|
78
84
|
Tooltip: react_bootstrap_5_1.Tooltip,
|
|
79
85
|
Glyphicon,
|
|
80
86
|
Modal: _Modal,
|
package/lib/translations.json
CHANGED
|
@@ -225,29 +225,34 @@
|
|
|
225
225
|
"sv": "Mb"
|
|
226
226
|
},
|
|
227
227
|
"allowedFileFormats": {
|
|
228
|
-
"fi": "Sallitut
|
|
229
|
-
"en": "Allowed
|
|
230
|
-
"sv": "Tillåtna filformat
|
|
228
|
+
"fi": "Sallitut tiedostoformaatit ovat",
|
|
229
|
+
"en": "Allowed file formats are",
|
|
230
|
+
"sv": "Tillåtna filformat är"
|
|
231
|
+
},
|
|
232
|
+
"allowedFileFormat": {
|
|
233
|
+
"fi": "Sallittu tiedostoformaatti on",
|
|
234
|
+
"en": "Allowed file format is",
|
|
235
|
+
"sv": "Tillåtet filformat är"
|
|
231
236
|
},
|
|
232
237
|
"allowedFileSize": {
|
|
233
|
-
"fi": "
|
|
238
|
+
"fi": "Tiedoston suurin sallittu koko on",
|
|
234
239
|
"en": "The maximum allowed file size is",
|
|
235
|
-
"sv": "Den största tillåtna
|
|
240
|
+
"sv": "Den största tillåtna filstorleken är"
|
|
236
241
|
},
|
|
237
242
|
"invalidFile": {
|
|
238
|
-
"fi": "
|
|
243
|
+
"fi": "Tiedosto oli virheellinen.",
|
|
239
244
|
"en": "The file was invalid.",
|
|
240
245
|
"sv": "Filen var ogiltig."
|
|
241
246
|
},
|
|
242
247
|
"insufficientSpace": {
|
|
243
|
-
"fi": "
|
|
244
|
-
"en": "The
|
|
245
|
-
"sv": "
|
|
248
|
+
"fi": "Mediapalvelin ei pysty käsittelemään latauspyyntöä riittämättömän levytilan vuoksi.",
|
|
249
|
+
"en": "The media server can't process the upload request because of insufficient space.",
|
|
250
|
+
"sv": "Mediaservern kan inte bearbeta uppladdnings begäran på grund av otillräckligt utrymme."
|
|
246
251
|
},
|
|
247
252
|
"filesLengthDiffer": {
|
|
248
|
-
"fi": "Kaikki
|
|
249
|
-
"en": "All the
|
|
250
|
-
"sv": "Alla
|
|
253
|
+
"fi": "Kaikki tiedostot eivät tallentuneet. Tarkista tiedostot.",
|
|
254
|
+
"en": "All the files weren't saved. Please verify the files.",
|
|
255
|
+
"sv": "Alla filer sparades inte. Vänligen kontrollera filerna."
|
|
251
256
|
},
|
|
252
257
|
"error": {
|
|
253
258
|
"fi": "Virhe",
|