@luomus/laji-form 15.1.53 → 15.1.55
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/dist/styles.css +7 -1
- package/lib/components/LajiForm.d.ts +2 -0
- package/lib/components/LajiForm.js +2 -0
- package/lib/components/fields/CondensedObjectField.d.ts +38 -0
- package/lib/components/fields/CondensedObjectField.js +146 -0
- package/lib/components/fields/ConditionalUiSchemaField.js +2 -2
- package/lib/components/fields/HiddenWithTextField.d.ts +18 -0
- package/lib/components/fields/HiddenWithTextField.js +20 -0
- package/lib/components/fields/MapField.d.ts +6 -1
- package/lib/components/fields/MapField.js +69 -29
- package/lib/components/widgets/AutosuggestWidget.js +6 -7
- package/lib/components/widgets/InputGroupWidget.d.ts +1 -1
- package/lib/components/widgets/InputGroupWidget.js +1 -1
- package/lib/components/widgets/SelectWidget.js +44 -43
- package/lib/translations.json +5 -0
- package/lib/utils.js +3 -0
- package/package.json +1 -1
- package/test-export/test-utils.js +10 -3
package/dist/styles.css
CHANGED
|
@@ -2091,7 +2091,7 @@ body .laji-form {
|
|
|
2091
2091
|
.laji-form .form-control, .laji-form .rw-widget, .laji-form .rw-widget-container, .laji-form-multiselect-input-wrapper {
|
|
2092
2092
|
border-radius: 2px !important;
|
|
2093
2093
|
}
|
|
2094
|
-
.laji-form label
|
|
2094
|
+
.laji-form label.btn {
|
|
2095
2095
|
border-radius: 2px;
|
|
2096
2096
|
line-height: 12.5px;
|
|
2097
2097
|
}
|
|
@@ -2142,6 +2142,9 @@ body .laji-form {
|
|
|
2142
2142
|
.laji-form .form-group {
|
|
2143
2143
|
margin-bottom: 5px;
|
|
2144
2144
|
}
|
|
2145
|
+
.laji-form .condensed-object-field-item .form-group {
|
|
2146
|
+
margin-bottom: 0;
|
|
2147
|
+
}
|
|
2145
2148
|
.laji-form .form-group-padding-bottom {
|
|
2146
2149
|
margin-bottom: 6px;
|
|
2147
2150
|
}
|
|
@@ -3795,6 +3798,9 @@ body .laji-form {
|
|
|
3795
3798
|
.laji-form .input-group.multi-lang-input-group .input-group-text {
|
|
3796
3799
|
width: 40px;
|
|
3797
3800
|
}
|
|
3801
|
+
.laji-form .input-group.condensed-object-field-input-group .input-group-text {
|
|
3802
|
+
min-width: 150px;
|
|
3803
|
+
}
|
|
3798
3804
|
|
|
3799
3805
|
.laji-form-multi-tag-array-field-buttons .btn-group-vertical {
|
|
3800
3806
|
margin-right: 17px;
|
|
@@ -59,6 +59,7 @@ const fields = importLocalComponents("fields", [
|
|
|
59
59
|
"AutoArrayField",
|
|
60
60
|
"AutosuggestField",
|
|
61
61
|
"HiddenField",
|
|
62
|
+
"HiddenWithTextField",
|
|
62
63
|
"InitiallyHiddenField",
|
|
63
64
|
"ContextInjectionField",
|
|
64
65
|
"ImageArrayField",
|
|
@@ -104,6 +105,7 @@ const fields = importLocalComponents("fields", [
|
|
|
104
105
|
"MultiTagArrayField",
|
|
105
106
|
"PdfArrayField",
|
|
106
107
|
"AsArrayField",
|
|
108
|
+
"CondensedObjectField",
|
|
107
109
|
{ "InputTransformerField": "ConditionalOnChangeField" },
|
|
108
110
|
{ "ConditionalField": "ConditionalUiSchemaField" },
|
|
109
111
|
{ "UnitRapidField": "UnitShorthandField" },
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as PropTypes from "prop-types";
|
|
3
|
+
import { FieldProps, JSONSchemaObject } from "../../types";
|
|
4
|
+
import * as memoize from "memoizee";
|
|
5
|
+
interface ArrayPropField {
|
|
6
|
+
type: "array";
|
|
7
|
+
name: string;
|
|
8
|
+
value?: string | number | boolean;
|
|
9
|
+
idx: number;
|
|
10
|
+
}
|
|
11
|
+
interface BasicPropField {
|
|
12
|
+
type: "string" | "number" | "boolean" | "object" | "integer";
|
|
13
|
+
name: string;
|
|
14
|
+
value?: string | number | boolean;
|
|
15
|
+
}
|
|
16
|
+
declare type SelectedField = ArrayPropField | BasicPropField;
|
|
17
|
+
interface State {
|
|
18
|
+
selectedFields: SelectedField[];
|
|
19
|
+
formData: any;
|
|
20
|
+
}
|
|
21
|
+
export default class CondensedObjectField extends React.Component<FieldProps<JSONSchemaObject>, State> {
|
|
22
|
+
static propTypes: {
|
|
23
|
+
schema: PropTypes.Validator<PropTypes.InferProps<{
|
|
24
|
+
type: PropTypes.Requireable<string>;
|
|
25
|
+
}>>;
|
|
26
|
+
formData: PropTypes.Requireable<object>;
|
|
27
|
+
};
|
|
28
|
+
static getName(): string;
|
|
29
|
+
constructor(props: FieldProps<JSONSchemaObject>);
|
|
30
|
+
componentDidUpdate(): void;
|
|
31
|
+
getSelectedFieldsFromProps(props: FieldProps<JSONSchemaObject>): SelectedField[];
|
|
32
|
+
onSelectFieldChange: (name: string) => void;
|
|
33
|
+
onFieldChange: ((idx: number) => (formData: any) => void) & memoize.Memoized<(idx: number) => (formData: any) => void>;
|
|
34
|
+
onFieldDelete: ((idx: number) => () => void) & memoize.Memoized<(idx: number) => () => void>;
|
|
35
|
+
getArrayFieldNextIdx(fields: SelectedField[], name: string): number;
|
|
36
|
+
render(): JSX.Element;
|
|
37
|
+
}
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const React = require("react");
|
|
4
|
+
const PropTypes = require("prop-types");
|
|
5
|
+
const SelectWidget_1 = require("../widgets/SelectWidget");
|
|
6
|
+
const utils_1 = require("../../utils");
|
|
7
|
+
const components_1 = require("../components");
|
|
8
|
+
const immutability_helper_1 = require("immutability-helper");
|
|
9
|
+
const memoize = require("memoizee");
|
|
10
|
+
const equals = require("deep-equal");
|
|
11
|
+
class CondensedObjectField extends React.Component {
|
|
12
|
+
constructor(props) {
|
|
13
|
+
super(props);
|
|
14
|
+
this.onSelectFieldChange = (name) => {
|
|
15
|
+
var _a;
|
|
16
|
+
if (!name) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const selectedFields = this.state.selectedFields;
|
|
20
|
+
const type = this.props.schema.properties[name].type;
|
|
21
|
+
let field;
|
|
22
|
+
let fieldFormData;
|
|
23
|
+
if (type !== "array") {
|
|
24
|
+
field = { type, name, value: undefined };
|
|
25
|
+
fieldFormData = undefined;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
field = { type, name, idx: this.getArrayFieldNextIdx(selectedFields, name), value: undefined };
|
|
29
|
+
fieldFormData = [...(((_a = this.props.formData) === null || _a === void 0 ? void 0 : _a[name]) || []), undefined];
|
|
30
|
+
}
|
|
31
|
+
const newSelectedFields = [...selectedFields, field];
|
|
32
|
+
const newFormData = Object.assign(Object.assign({}, (this.props.formData || {})), { [name]: fieldFormData });
|
|
33
|
+
this.setState({ selectedFields: newSelectedFields, formData: newFormData });
|
|
34
|
+
this.props.onChange(newFormData);
|
|
35
|
+
};
|
|
36
|
+
this.onFieldChange = memoize((idx) => (formData) => {
|
|
37
|
+
const selectedFields = this.state.selectedFields;
|
|
38
|
+
const field = selectedFields[idx];
|
|
39
|
+
let newSelectedFields = immutability_helper_1.default(selectedFields, { [idx]: { ["value"]: { $set: formData } } });
|
|
40
|
+
let newFormData;
|
|
41
|
+
if (field.type !== "array") {
|
|
42
|
+
newFormData = Object.assign(Object.assign({}, this.props.formData), { [field.name]: formData });
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
newFormData = immutability_helper_1.default(this.props.formData, { [field.name]: { [field.idx]: { $set: formData } } });
|
|
46
|
+
}
|
|
47
|
+
this.setState({ selectedFields: newSelectedFields, formData: newFormData });
|
|
48
|
+
this.props.onChange(newFormData);
|
|
49
|
+
});
|
|
50
|
+
this.onFieldDelete = memoize((idx) => () => {
|
|
51
|
+
const selectedFields = this.state.selectedFields;
|
|
52
|
+
const field = selectedFields[idx];
|
|
53
|
+
let newSelectedFields = immutability_helper_1.default(selectedFields, { $splice: [[idx, 1]] });
|
|
54
|
+
let newFormData;
|
|
55
|
+
if (field.type !== "array" || this.props.formData[field.name].length === 1) {
|
|
56
|
+
newFormData = immutability_helper_1.default(this.props.formData, { $unset: [field.name] });
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
newSelectedFields.forEach((f, idx) => {
|
|
60
|
+
if (f.type === "array" && f.name === field.name && f.idx > field.idx) {
|
|
61
|
+
newSelectedFields = immutability_helper_1.default(newSelectedFields, { [idx]: { ["idx"]: { $set: f.idx - 1 } } });
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
newFormData = immutability_helper_1.default(this.props.formData, { [field.name]: { $splice: [[field.idx, 1]] } });
|
|
65
|
+
}
|
|
66
|
+
if (Object.keys(newFormData).length === 0) {
|
|
67
|
+
newFormData = undefined;
|
|
68
|
+
}
|
|
69
|
+
this.setState({ selectedFields: newSelectedFields, formData: newFormData });
|
|
70
|
+
this.props.onChange(newFormData);
|
|
71
|
+
});
|
|
72
|
+
this.state = { selectedFields: this.getSelectedFieldsFromProps(props), formData: props.formData };
|
|
73
|
+
}
|
|
74
|
+
static getName() { return "CondensedObjectField"; }
|
|
75
|
+
componentDidUpdate() {
|
|
76
|
+
if (!equals(this.props.formData, this.state.formData)) {
|
|
77
|
+
this.setState({ selectedFields: this.getSelectedFieldsFromProps(this.props), formData: this.props.formData });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
getSelectedFieldsFromProps(props) {
|
|
81
|
+
const { formData, schema } = props;
|
|
82
|
+
const selectedFields = [];
|
|
83
|
+
Object.keys(formData || {}).forEach(key => {
|
|
84
|
+
const type = schema.properties[key].type;
|
|
85
|
+
if (type !== "array") {
|
|
86
|
+
selectedFields.push({ type, name: key, value: formData[key] });
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
formData[key].forEach((data, idx) => {
|
|
90
|
+
selectedFields.push({ type, name: key, idx, value: data });
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
return selectedFields;
|
|
95
|
+
}
|
|
96
|
+
getArrayFieldNextIdx(fields, name) {
|
|
97
|
+
const oldIndexes = fields.filter(f => f.name === name).map(f => (f.type === "array" ? f.idx : -1));
|
|
98
|
+
return Math.max(...oldIndexes, -1) + 1;
|
|
99
|
+
}
|
|
100
|
+
render() {
|
|
101
|
+
var _a;
|
|
102
|
+
const SchemaField = this.props.registry.fields.SchemaField;
|
|
103
|
+
const { schema, uiSchema, idSchema, errorSchema, formData = {}, required, formContext: { Label, translations } } = this.props;
|
|
104
|
+
const uiOptions = utils_1.getUiOptions(uiSchema);
|
|
105
|
+
const childProps = this.state.selectedFields.map(field => {
|
|
106
|
+
let childSchema = schema.properties[field.name];
|
|
107
|
+
let childUiSchema = uiSchema[field.name] || {};
|
|
108
|
+
let childIdSchema = idSchema[field.name] || { $id: `${idSchema.$id}_${field.name}` };
|
|
109
|
+
let childErrorSchema = errorSchema[field.name] || {};
|
|
110
|
+
let childFormData = formData[field.name];
|
|
111
|
+
if (field.type === "array" && childSchema.type === "array") {
|
|
112
|
+
childSchema = childSchema.items;
|
|
113
|
+
childIdSchema = Object.assign(Object.assign({}, childIdSchema), { $id: `${childIdSchema.$id}_${field.idx}` });
|
|
114
|
+
childErrorSchema = childErrorSchema[field.idx] || {};
|
|
115
|
+
childFormData = childFormData === null || childFormData === void 0 ? void 0 : childFormData[field.idx];
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
schema: childSchema,
|
|
119
|
+
uiSchema: Object.assign(Object.assign({}, childUiSchema), { "ui:title": "", "ui:widget": "InputGroupWidget", "ui:options": Object.assign({ "inputGroupText": schema.properties[field.name].title || field.name, "className": "condensed-object-field-input-group" }, (childUiSchema["ui:options"] || {})) }),
|
|
120
|
+
idSchema: childIdSchema,
|
|
121
|
+
errorSchema: childErrorSchema,
|
|
122
|
+
formData: childFormData
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
const selectableFieldEnums = Object.keys(schema.properties).filter(prop => schema.properties[prop].type === "array" || !this.state.selectedFields.some(field => field.name === prop)).map(prop => ({
|
|
126
|
+
value: prop,
|
|
127
|
+
label: schema.properties[prop].title || prop,
|
|
128
|
+
}));
|
|
129
|
+
const addFieldPlaceholder = (_a = uiOptions.addFieldPlaceholder) !== null && _a !== void 0 ? _a : `${translations.AddField}`;
|
|
130
|
+
return (React.createElement(React.Fragment, null,
|
|
131
|
+
React.createElement(Label, { label: this.props.schema.title, required: required || uiSchema["ui:required"], id: this.props.idSchema.$id, uiSchema: this.props.uiSchema }),
|
|
132
|
+
childProps.map((props, idx) => React.createElement("div", { key: idx, className: "laji-form-field-template-item condensed-object-field-item" },
|
|
133
|
+
React.createElement("div", { className: "laji-form-field-template-schema" },
|
|
134
|
+
React.createElement(SchemaField, Object.assign({}, this.props, props, { key: idx, onChange: this.onFieldChange(idx) }))),
|
|
135
|
+
React.createElement("div", { className: "laji-form-field-template-buttons" },
|
|
136
|
+
React.createElement(components_1.DeleteButton, { id: props.idSchema.$id, onClick: this.onFieldDelete(idx), translations: translations })))),
|
|
137
|
+
React.createElement(SelectWidget_1.default, { key: childProps.length, options: { enumOptions: selectableFieldEnums, placeholder: addFieldPlaceholder }, onChange: this.onSelectFieldChange, includeEmpty: true, schema: {}, id: `${idSchema.$id}_field_select`, formContext: this.props.formContext })));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
exports.default = CondensedObjectField;
|
|
141
|
+
CondensedObjectField.propTypes = {
|
|
142
|
+
schema: PropTypes.shape({
|
|
143
|
+
type: PropTypes.oneOf(["object"])
|
|
144
|
+
}).isRequired,
|
|
145
|
+
formData: PropTypes.object
|
|
146
|
+
};
|
|
@@ -22,10 +22,10 @@ exports.rulePropType = PropTypes.oneOfType([
|
|
|
22
22
|
complement: PropTypes.bool
|
|
23
23
|
}),
|
|
24
24
|
PropTypes.shape({
|
|
25
|
-
rule: PropTypes.oneOf(["isAdmin", "isEdit", "isReadonly"]),
|
|
25
|
+
rule: PropTypes.oneOf(["isAdmin", "isLoggedIn", "isEdit", "isReadonly"]),
|
|
26
26
|
complement: PropTypes.bool
|
|
27
27
|
}),
|
|
28
|
-
PropTypes.oneOf(["isAdmin", "isEdit", "isReadonly"]),
|
|
28
|
+
PropTypes.oneOf(["isAdmin", "isLoggedIn", "isEdit", "isReadonly"]),
|
|
29
29
|
]);
|
|
30
30
|
exports.operationPropType = PropTypes.shape({
|
|
31
31
|
type: PropTypes.oneOf(["merge", "wrap"]),
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import * as PropTypes from "prop-types";
|
|
3
|
+
import { FieldProps, JSONSchemaArray, JSONSchemaString } from "../../types";
|
|
4
|
+
declare const HiddenWithTextField: {
|
|
5
|
+
(props: FieldProps<JSONSchemaArray<JSONSchemaString>>): JSX.Element;
|
|
6
|
+
propTypes: {
|
|
7
|
+
uiSchema: PropTypes.Validator<PropTypes.InferProps<{
|
|
8
|
+
"ui:options": PropTypes.Validator<PropTypes.InferProps<{
|
|
9
|
+
altText: PropTypes.Validator<string>;
|
|
10
|
+
}>>;
|
|
11
|
+
uiSchema: PropTypes.Requireable<object>;
|
|
12
|
+
}>>;
|
|
13
|
+
schema: PropTypes.Validator<PropTypes.InferProps<{
|
|
14
|
+
type: PropTypes.Requireable<string>;
|
|
15
|
+
}>>;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export default HiddenWithTextField;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const React = require("react");
|
|
4
|
+
const PropTypes = require("prop-types");
|
|
5
|
+
const HiddenWithTextField = (props) => {
|
|
6
|
+
var _a;
|
|
7
|
+
return (React.createElement("div", null, (_a = props.uiSchema["ui:options"]) === null || _a === void 0 ? void 0 : _a.altText));
|
|
8
|
+
};
|
|
9
|
+
HiddenWithTextField.propTypes = {
|
|
10
|
+
uiSchema: PropTypes.shape({
|
|
11
|
+
"ui:options": PropTypes.shape({
|
|
12
|
+
"altText": PropTypes.string.isRequired
|
|
13
|
+
}).isRequired,
|
|
14
|
+
uiSchema: PropTypes.object
|
|
15
|
+
}).isRequired,
|
|
16
|
+
schema: PropTypes.shape({
|
|
17
|
+
type: PropTypes.oneOf(["object", "array", "string", "number", "boolean", "integer"])
|
|
18
|
+
}).isRequired
|
|
19
|
+
};
|
|
20
|
+
exports.default = HiddenWithTextField;
|
|
@@ -14,6 +14,10 @@ export default class MapField extends React.Component<any, any, any> {
|
|
|
14
14
|
height: PropTypes.Requireable<number>;
|
|
15
15
|
emptyHelp: PropTypes.Requireable<string>;
|
|
16
16
|
geometryCollection: PropTypes.Requireable<boolean>;
|
|
17
|
+
coordinateFields: PropTypes.Requireable<PropTypes.InferProps<{
|
|
18
|
+
latitude: PropTypes.Validator<string>;
|
|
19
|
+
longitude: PropTypes.Validator<string>;
|
|
20
|
+
}>>;
|
|
17
21
|
}>>;
|
|
18
22
|
}>>;
|
|
19
23
|
schema: PropTypes.Validator<PropTypes.InferProps<{
|
|
@@ -33,12 +37,13 @@ export default class MapField extends React.Component<any, any, any> {
|
|
|
33
37
|
getDrawOptions: (props: any) => any;
|
|
34
38
|
getGeometry: (props: any) => any;
|
|
35
39
|
getMobileGeometry: () => any;
|
|
40
|
+
getFormDataFromGeometry: (geometry: any) => any;
|
|
36
41
|
setMoved: (moved: any) => void;
|
|
37
42
|
onOptionsChanged: (options: any) => void;
|
|
38
43
|
onChange: (events: any) => void;
|
|
39
44
|
onMobileEditorChange: (point: any) => void;
|
|
40
45
|
onHideMobileEditorMap: (options: any) => void;
|
|
41
|
-
onLocate: (latlng: any, forceShow: any) => void;
|
|
46
|
+
onLocate: (latlng: any, radius: any, forceShow: any) => void;
|
|
42
47
|
onLocateError: () => void;
|
|
43
48
|
renderBlocker(): JSX.Element | undefined;
|
|
44
49
|
}
|
|
@@ -108,25 +108,35 @@ class MapField extends React.Component {
|
|
|
108
108
|
this.getDrawOptions = (props) => {
|
|
109
109
|
const { uiSchema, disabled, readonly } = props;
|
|
110
110
|
const options = utils_1.getUiOptions(uiSchema);
|
|
111
|
-
const { mapOptions = {} } = options;
|
|
111
|
+
const { mapOptions = {}, coordinateFields } = options;
|
|
112
112
|
const drawOptions = Object.assign(Object.assign({}, (mapOptions.draw || {})), { geoData: this.getGeometry(props), onChange: this.onChange, editable: !disabled && !readonly && !options.mobileEditor });
|
|
113
|
+
if (coordinateFields) {
|
|
114
|
+
["rectangle", "polygon", "polyline", "circle"].forEach(drawType => {
|
|
115
|
+
drawOptions[drawType] = false;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
113
118
|
return drawOptions;
|
|
114
119
|
};
|
|
115
120
|
this.getGeometry = (props) => {
|
|
116
121
|
const { formData } = props;
|
|
122
|
+
const { coordinateFields } = utils_1.getUiOptions(this.props.uiSchema);
|
|
123
|
+
if (coordinateFields) {
|
|
124
|
+
if ((formData === null || formData === void 0 ? void 0 : formData[coordinateFields.longitude]) !== undefined && (formData === null || formData === void 0 ? void 0 : formData[coordinateFields.latitude]) !== undefined) {
|
|
125
|
+
return {
|
|
126
|
+
type: "Point",
|
|
127
|
+
coordinates: [formData[coordinateFields.longitude], formData[coordinateFields.latitude]]
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
117
134
|
return formData && Object.keys(formData).length ? formData : undefined;
|
|
118
135
|
};
|
|
119
136
|
this.getMobileGeometry = () => {
|
|
120
|
-
var _a;
|
|
121
137
|
if (this.props.formData) {
|
|
122
138
|
return this.props.formData;
|
|
123
139
|
}
|
|
124
|
-
else if ((_a = this.map) === null || _a === void 0 ? void 0 : _a.userLocation) {
|
|
125
|
-
return {
|
|
126
|
-
type: "Point",
|
|
127
|
-
coordinates: [this.map.userLocation.latlng.lng, this.map.userLocation.latlng.lat]
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
140
|
else {
|
|
131
141
|
return {
|
|
132
142
|
type: "Point",
|
|
@@ -134,6 +144,23 @@ class MapField extends React.Component {
|
|
|
134
144
|
};
|
|
135
145
|
}
|
|
136
146
|
};
|
|
147
|
+
this.getFormDataFromGeometry = (geometry) => {
|
|
148
|
+
const { geometryCollection = true, coordinateFields } = utils_1.getUiOptions(this.props.uiSchema);
|
|
149
|
+
let formData;
|
|
150
|
+
if (coordinateFields) {
|
|
151
|
+
formData = geometry ? {
|
|
152
|
+
[coordinateFields.longitude]: geometry.coordinates[0],
|
|
153
|
+
[coordinateFields.latitude]: geometry.coordinates[1]
|
|
154
|
+
} : undefined;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
formData = geometryCollection ? {
|
|
158
|
+
type: "GeometryCollection",
|
|
159
|
+
geometries: geometry ? [geometry] : []
|
|
160
|
+
} : geometry || {};
|
|
161
|
+
}
|
|
162
|
+
return formData;
|
|
163
|
+
};
|
|
137
164
|
this.setMoved = (moved) => {
|
|
138
165
|
this.setState({ moved });
|
|
139
166
|
};
|
|
@@ -141,27 +168,17 @@ class MapField extends React.Component {
|
|
|
141
168
|
this.setState({ mapOptions: Object.assign(Object.assign({}, this.state.mapOptions), options) });
|
|
142
169
|
};
|
|
143
170
|
this.onChange = (events) => {
|
|
144
|
-
const { geometryCollection = true } = utils_1.getUiOptions(this.props.uiSchema);
|
|
145
171
|
let formData;
|
|
146
172
|
events.forEach(e => {
|
|
147
173
|
switch (e.type) {
|
|
148
174
|
case "create":
|
|
149
|
-
formData =
|
|
150
|
-
type: "GeometryCollection",
|
|
151
|
-
geometries: [e.feature.geometry]
|
|
152
|
-
} : e.feature.geometry;
|
|
175
|
+
formData = this.getFormDataFromGeometry(e.feature.geometry);
|
|
153
176
|
break;
|
|
154
177
|
case "edit":
|
|
155
|
-
formData =
|
|
156
|
-
type: "GeometryCollection",
|
|
157
|
-
geometries: [e.features[0].geometry]
|
|
158
|
-
} : e.features[0].geometry;
|
|
178
|
+
formData = this.getFormDataFromGeometry(e.features[0].geometry);
|
|
159
179
|
break;
|
|
160
180
|
case "delete":
|
|
161
|
-
formData =
|
|
162
|
-
type: "GeometryCollection",
|
|
163
|
-
geometries: []
|
|
164
|
-
} : {};
|
|
181
|
+
formData = this.getFormDataFromGeometry(undefined);
|
|
165
182
|
}
|
|
166
183
|
});
|
|
167
184
|
this._zoomToDataOnNextTick = true;
|
|
@@ -183,8 +200,8 @@ class MapField extends React.Component {
|
|
|
183
200
|
this.onHideMobileEditorMap = (options) => {
|
|
184
201
|
this.setState({ mobileEditor: { visible: false, options } });
|
|
185
202
|
};
|
|
186
|
-
this.onLocate = (latlng, forceShow) => {
|
|
187
|
-
const {
|
|
203
|
+
this.onLocate = (latlng, radius, forceShow) => {
|
|
204
|
+
const { mobileEditor, createOnLocate } = utils_1.getUiOptions(this.props.uiSchema);
|
|
188
205
|
const isEmpty = !this.getGeometry(this.props);
|
|
189
206
|
if (!latlng || !isEmpty) {
|
|
190
207
|
this.setState({ located: true });
|
|
@@ -205,7 +222,7 @@ class MapField extends React.Component {
|
|
|
205
222
|
this.setState({ located: true });
|
|
206
223
|
if (createOnLocate) {
|
|
207
224
|
const geometry = { type: "Point", coordinates: [latlng.lng, latlng.lat] };
|
|
208
|
-
this.props.onChange(
|
|
225
|
+
this.props.onChange(this.getFormDataFromGeometry(geometry));
|
|
209
226
|
}
|
|
210
227
|
};
|
|
211
228
|
this.onLocateError = () => {
|
|
@@ -233,6 +250,10 @@ class MapField extends React.Component {
|
|
|
233
250
|
}
|
|
234
251
|
this.geocode(this.props);
|
|
235
252
|
this.props.formContext.services.customEvents.add(this.props.idSchema.$id, "locate", this.onLocateEventHandler);
|
|
253
|
+
const { mobileEditor } = utils_1.getUiOptions(uiSchema);
|
|
254
|
+
if (mobileEditor) {
|
|
255
|
+
this.showMobileEditorMap();
|
|
256
|
+
}
|
|
236
257
|
}
|
|
237
258
|
componentWillUnmount() {
|
|
238
259
|
this.props.formContext.services.customEvents.remove(this.props.idSchema.$id, "locate", this.onLocateEventHandler);
|
|
@@ -267,7 +288,7 @@ class MapField extends React.Component {
|
|
|
267
288
|
singletonHasLocate = map.getOptions().locate;
|
|
268
289
|
}
|
|
269
290
|
}
|
|
270
|
-
if (mapOptions.createOnLocate && !this.state.mapOptions && (!singletonRendered || singletonHasLocate)) {
|
|
291
|
+
if (mapOptions.createOnLocate && !this.state.mapOptions && (!singletonRendered || singletonHasLocate) && !_mobileEditor) {
|
|
271
292
|
_mapOptions.locate.on = true;
|
|
272
293
|
}
|
|
273
294
|
if (_mobileEditor) {
|
|
@@ -317,6 +338,10 @@ MapField.propTypes = {
|
|
|
317
338
|
height: PropTypes.number,
|
|
318
339
|
emptyHelp: PropTypes.string,
|
|
319
340
|
geometryCollection: PropTypes.bool,
|
|
341
|
+
coordinateFields: PropTypes.shape({
|
|
342
|
+
latitude: PropTypes.string.isRequired,
|
|
343
|
+
longitude: PropTypes.string.isRequired
|
|
344
|
+
})
|
|
320
345
|
})
|
|
321
346
|
}),
|
|
322
347
|
schema: PropTypes.shape({
|
|
@@ -374,12 +399,26 @@ class MobileEditorMap extends React.Component {
|
|
|
374
399
|
this.onClose();
|
|
375
400
|
}
|
|
376
401
|
};
|
|
402
|
+
this.onLocate = (latlng) => {
|
|
403
|
+
if (!latlng || this.state.located) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
this.map.map.setView({ lng: latlng.lng, lat: latlng.lat }, 12);
|
|
407
|
+
this.setMarkerLatLng(latlng);
|
|
408
|
+
if (!this.state.located) {
|
|
409
|
+
this.setState({ located: true });
|
|
410
|
+
}
|
|
411
|
+
if (!this.props.moved) {
|
|
412
|
+
this.props.setMoved(true);
|
|
413
|
+
}
|
|
414
|
+
};
|
|
377
415
|
this.onClose = () => {
|
|
378
416
|
this.props.onClose(this.map.getOptions());
|
|
379
417
|
};
|
|
380
418
|
const { geometry } = this.props;
|
|
381
419
|
this.state = {
|
|
382
|
-
geometry: [{ geoData: geometry }]
|
|
420
|
+
geometry: [{ geoData: geometry }],
|
|
421
|
+
located: false
|
|
383
422
|
};
|
|
384
423
|
}
|
|
385
424
|
componentDidMount() {
|
|
@@ -415,15 +454,16 @@ class MobileEditorMap extends React.Component {
|
|
|
415
454
|
const { userLocation } = this.props;
|
|
416
455
|
const { translations } = this.props.formContext;
|
|
417
456
|
const mapComponentProps = Object.assign(Object.assign(Object.assign({}, options), (this.props.options || {})), { locate: {
|
|
418
|
-
on:
|
|
457
|
+
on: false,
|
|
419
458
|
userLocation,
|
|
420
|
-
|
|
459
|
+
onLocationFound: this.onLocate,
|
|
460
|
+
panOnFound: false
|
|
421
461
|
}, singleton: true, clickBeforeZoomAndPan: false, viewLocked: false, controls: { draw: false }, ref: this.setMobileEditorMapRef, formContext: this.props.formContext, panel: {
|
|
422
462
|
panelTextContent: this.props.formContext.translations.MobileMapInstructions
|
|
423
463
|
} });
|
|
424
464
|
return (React.createElement(components_2.Fullscreen, { onKeyDown: this.onKeyDown, tabIndex: -1, ref: this.setContainerRef, formContext: this.props.formContext },
|
|
425
465
|
React.createElement(MapArrayField_1.MapComponent, Object.assign({}, mapComponentProps)),
|
|
426
466
|
React.createElement("div", { className: "floating-buttons-container" },
|
|
427
|
-
React.createElement(components_2.Button, { block: true, onClick: this.onChange, variant: "primary", ref: this.setOkButtonRef, disabled: !this.props.moved }, translations.ChooseThisLocation))));
|
|
467
|
+
React.createElement(components_2.Button, { block: true, onClick: this.onChange, className: "choose-location-button", variant: "primary", ref: this.setOkButtonRef, disabled: !this.props.moved }, translations.ChooseThisLocation))));
|
|
428
468
|
}
|
|
429
469
|
}
|
|
@@ -1026,7 +1026,8 @@ class ReactAutosuggest extends React.Component {
|
|
|
1026
1026
|
this.onBlur(e);
|
|
1027
1027
|
};
|
|
1028
1028
|
this.onInputKeyDown = (e) => {
|
|
1029
|
-
|
|
1029
|
+
var _a, _b;
|
|
1030
|
+
let state;
|
|
1030
1031
|
switch (e.key) {
|
|
1031
1032
|
case "ArrowDown":
|
|
1032
1033
|
e.preventDefault();
|
|
@@ -1056,10 +1057,7 @@ class ReactAutosuggest extends React.Component {
|
|
|
1056
1057
|
break;
|
|
1057
1058
|
case "Enter":
|
|
1058
1059
|
e.preventDefault();
|
|
1059
|
-
|
|
1060
|
-
if (suggestion) {
|
|
1061
|
-
this.onSuggestionSelected(suggestion);
|
|
1062
|
-
}
|
|
1060
|
+
this.inputElem.blur();
|
|
1063
1061
|
break;
|
|
1064
1062
|
case "Control":
|
|
1065
1063
|
case "Meta":
|
|
@@ -1070,7 +1068,7 @@ class ReactAutosuggest extends React.Component {
|
|
|
1070
1068
|
default:
|
|
1071
1069
|
this.setState({ touched: true });
|
|
1072
1070
|
}
|
|
1073
|
-
this.props.inputProps
|
|
1071
|
+
(_b = (_a = this.props.inputProps) === null || _a === void 0 ? void 0 : _a.onKeyDown) === null || _b === void 0 ? void 0 : _b.call(_a, e);
|
|
1074
1072
|
};
|
|
1075
1073
|
this.onInputChange = (e) => {
|
|
1076
1074
|
this._onInputChange(e.target.value, "keystroke");
|
|
@@ -1121,13 +1119,14 @@ class ReactAutosuggest extends React.Component {
|
|
|
1121
1119
|
this.renderSuggestions()));
|
|
1122
1120
|
}
|
|
1123
1121
|
onBlur(e) {
|
|
1122
|
+
var _a, _b;
|
|
1124
1123
|
if (e.relatedTarget && e.relatedTarget === react_dom_1.findDOMNode(this.listRef.current)) {
|
|
1125
1124
|
return;
|
|
1126
1125
|
}
|
|
1127
1126
|
const suggestion = (this.props.suggestions || [])[this.state.focusedIdx];
|
|
1128
1127
|
suggestion && this.onSuggestionSelected(this.props.suggestions[this.state.focusedIdx]);
|
|
1129
1128
|
this.setState({ focused: false, focusedIdx: undefined, touched: false });
|
|
1130
|
-
this.props.inputProps
|
|
1129
|
+
(_b = (_a = this.props.inputProps) === null || _a === void 0 ? void 0 : _a.onBlur) === null || _b === void 0 ? void 0 : _b.call(_a, e);
|
|
1131
1130
|
}
|
|
1132
1131
|
renderInput() {
|
|
1133
1132
|
const { inputProps, renderInputComponent = this.renderDefaultInputComponent } = this.props;
|
|
@@ -11,7 +11,7 @@ export default class InputGroupWidget extends React.Component<any, any, any> {
|
|
|
11
11
|
schema: PropTypes.Validator<PropTypes.InferProps<{
|
|
12
12
|
type: PropTypes.Requireable<string>;
|
|
13
13
|
}>>;
|
|
14
|
-
value: PropTypes.Requireable<string>;
|
|
14
|
+
value: PropTypes.Requireable<string | number>;
|
|
15
15
|
required: PropTypes.Requireable<boolean>;
|
|
16
16
|
};
|
|
17
17
|
constructor(props: any);
|
|
@@ -31,6 +31,6 @@ InputGroupWidget.propTypes = {
|
|
|
31
31
|
schema: PropTypes.shape({
|
|
32
32
|
type: PropTypes.oneOf(["string", "number", "integer"]),
|
|
33
33
|
}).isRequired,
|
|
34
|
-
value: PropTypes.string,
|
|
34
|
+
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
35
35
|
required: PropTypes.bool
|
|
36
36
|
};
|