@luomus/laji-form 15.1.57 → 15.1.59

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.
Files changed (44) hide show
  1. package/dist/laji-form.js +1 -1
  2. package/lib/components/LajiForm.d.ts +6 -2
  3. package/lib/components/VirtualSchemaField.d.ts +9 -9
  4. package/lib/components/VirtualSchemaField.js +1 -1
  5. package/lib/components/fields/ArrayPropertySumField.d.ts +1 -1
  6. package/lib/components/fields/AsArrayField.d.ts +3 -393
  7. package/lib/components/fields/CondensedObjectField.d.ts +3 -3
  8. package/lib/components/fields/ExtraLabelRowField.d.ts +1 -1
  9. package/lib/components/fields/ImageArrayField.d.ts +11 -11
  10. package/lib/components/fields/InitiallyHiddenField.d.ts +1 -1
  11. package/lib/components/fields/LocationChooserField.d.ts +1 -1
  12. package/lib/components/fields/MapArrayField.js +6 -1
  13. package/lib/components/fields/MapField.js +17 -7
  14. package/lib/components/fields/MultiTagArrayField.js +1 -1
  15. package/lib/components/fields/NamedPlaceChooserField/NamedPlaceChooser.d.ts +54 -0
  16. package/lib/components/fields/NamedPlaceChooserField/NamedPlaceChooser.js +169 -0
  17. package/lib/components/fields/NamedPlaceChooserField/NamedPlaceChooserField.d.ts +71 -0
  18. package/lib/components/fields/NamedPlaceChooserField/NamedPlaceChooserField.js +193 -0
  19. package/lib/components/fields/NamedPlaceChooserField/Popup.d.ts +12 -0
  20. package/lib/components/fields/NamedPlaceChooserField/Popup.js +67 -0
  21. package/lib/components/fields/NamedPlaceChooserField/index.d.ts +1 -0
  22. package/lib/components/fields/NamedPlaceChooserField/index.js +8 -0
  23. package/lib/components/fields/NamedPlaceSaverField.d.ts +16 -16
  24. package/lib/components/fields/PdfArrayField.d.ts +1 -1
  25. package/lib/components/fields/SchemaField.d.ts +5 -6
  26. package/lib/components/fields/SchemaField.js +4 -24
  27. package/lib/components/fields/ScopeField.d.ts +1 -1
  28. package/lib/components/fields/SelectTreeField.js +1 -1
  29. package/lib/components/fields/SortArrayField.d.ts +32 -32
  30. package/lib/components/fields/SplitField.js +1 -1
  31. package/lib/components/fields/StringToArrayField.d.ts +17 -17
  32. package/lib/components/fields/ToggleAdditionalArrayFieldsField.d.ts +1 -1
  33. package/lib/components/fields/UnitListShorthandArrayField.d.ts +16 -16
  34. package/lib/components/widgets/SelectWidget.d.ts +15 -14
  35. package/lib/components/widgets/SelectWidget.js +37 -26
  36. package/lib/services/submit-hook-service.d.ts +1 -1
  37. package/lib/translations.json +5 -0
  38. package/lib/types.d.ts +8 -10
  39. package/lib/types.js +5 -1
  40. package/lib/utils.d.ts +5 -4
  41. package/lib/utils.js +8 -8
  42. package/package.json +3 -2
  43. package/lib/components/fields/NamedPlaceChooserField.d.ts +0 -115
  44. package/lib/components/fields/NamedPlaceChooserField.js +0 -402
@@ -420,14 +420,21 @@ class MobileEditorMap extends React.Component {
420
420
  this.onClose();
421
421
  }
422
422
  };
423
+ this.activateLocate = () => {
424
+ this.handleLocateToggle(true);
425
+ };
426
+ this.handleLocateToggle = (bool) => {
427
+ this.setState({ locateActive: bool, hasLocated: false });
428
+ this.map.setOption("locate", { on: bool });
429
+ };
423
430
  this.onLocate = (latlng) => {
424
- if (!latlng || this.state.located) {
431
+ if (!latlng || this.state.hasLocated) {
425
432
  return;
426
433
  }
427
434
  this.map.map.setView({ lng: latlng.lng, lat: latlng.lat }, 12);
428
435
  this.setMarkerLatLng(latlng);
429
- if (!this.state.located) {
430
- this.setState({ located: true });
436
+ if (!this.state.hasLocated) {
437
+ this.setState({ hasLocated: true });
431
438
  }
432
439
  if (!this.props.moved) {
433
440
  this.props.setMoved(true);
@@ -439,12 +446,14 @@ class MobileEditorMap extends React.Component {
439
446
  const { geometry } = this.props;
440
447
  this.state = {
441
448
  geometry: [{ geoData: geometry }],
442
- located: false
449
+ locateActive: false,
450
+ hasLocated: false
443
451
  };
444
452
  }
445
453
  componentDidMount() {
446
454
  this.mounted = true;
447
455
  this.okButtonElem.focus();
456
+ this.map.setLocateOff();
448
457
  if (this.props.geometry) {
449
458
  const [lng, lat] = this.props.geometry.coordinates;
450
459
  this.setMarkerLatLng({ lng, lat });
@@ -475,7 +484,7 @@ class MobileEditorMap extends React.Component {
475
484
  const { userLocation } = this.props;
476
485
  const { translations } = this.props.formContext;
477
486
  const mapComponentProps = Object.assign(Object.assign(Object.assign({}, options), (this.props.options || {})), { locate: {
478
- on: false,
487
+ on: this.state.locateActive,
479
488
  userLocation,
480
489
  onLocationFound: this.onLocate,
481
490
  panOnFound: false
@@ -483,8 +492,9 @@ class MobileEditorMap extends React.Component {
483
492
  panelTextContent: this.props.formContext.translations.MobileMapInstructions
484
493
  } });
485
494
  return (React.createElement(components_1.Fullscreen, { onKeyDown: this.onKeyDown, tabIndex: -1, ref: this.setContainerRef, formContext: this.props.formContext },
486
- React.createElement(MapArrayField_1.MapComponent, Object.assign({}, mapComponentProps)),
495
+ React.createElement(MapArrayField_1.MapComponent, Object.assign({}, mapComponentProps, { onLocateToggle: this.handleLocateToggle })),
487
496
  React.createElement("div", { className: "floating-buttons-container" },
488
- React.createElement(components_1.Button, { block: true, onClick: this.onChange, className: "choose-location-button", variant: "primary", ref: this.setOkButtonRef, disabled: !this.props.moved }, translations.ChooseThisLocation))));
497
+ React.createElement(components_1.Button, { block: true, onClick: this.onChange, className: "choose-location-button", variant: "primary", ref: this.setOkButtonRef, disabled: !this.props.moved }, translations.ChooseThisLocation),
498
+ React.createElement(components_1.Button, { block: true, onClick: this.activateLocate, className: "locate-me-button", variant: "default", disabled: this.state.locateActive }, translations.LocateMe))));
489
499
  }
490
500
  }
@@ -118,7 +118,7 @@ let MultiTagArrayField = class MultiTagArrayField extends React.Component {
118
118
  React.createElement("div", { className: "btn-group-vertical" }, buttons.map((btnProps, idx) => (React.createElement(components_1.Button, { key: idx, onClick: this.onButtonClick(idx), variant: btnProps.operation === "delete" ? "outline-danger" : "default", className: utils_1.classNames(btnProps.className, activeButtonIdx === idx ? "active" : ""), disabled: disabled || readonly }, btnProps.label)))))),
119
119
  React.createElement(Col, { xs: 9, sm: 9, md: 10, lg: 10, className: "laji-form-multi-tag-array-field-content" }, propertyKeys.map(key => {
120
120
  var _a, _b;
121
- return (React.createElement(SchemaField, Object.assign({}, this.props, { key: key, schema: Object.assign({ title: "" }, schema.properties[key]), uiSchema: Object.assign(Object.assign({ "ui:field": "TagArrayField" }, uiSchema[key]), { "ui:options": Object.assign(Object.assign(Object.assign({}, uiOptions), { buttons: undefined, onTagClick: this.onTagClick(key) }), (_a = uiSchema[key]) === null || _a === void 0 ? void 0 : _a["ui:options"]) }), errorSchema: errorSchema[key] || {}, idSchema: idSchema[key], formData: formData[key] || [], required: ((_b = uiSchema[key]) === null || _b === void 0 ? void 0 : _b["ui:required"]) || false, onChange: this.onChange(key) })));
121
+ return (React.createElement(SchemaField, Object.assign({}, this.props, { key: key, schema: Object.assign({ title: "" }, schema.properties[key]), uiSchema: Object.assign(Object.assign({ "ui:field": "TagArrayField" }, uiSchema[key]), { "ui:options": Object.assign(Object.assign(Object.assign({}, uiOptions), { buttons: undefined, onTagClick: this.onTagClick(key) }), (_a = uiSchema[key]) === null || _a === void 0 ? void 0 : _a["ui:options"]) }), errorSchema: errorSchema[key] || {}, idSchema: idSchema[key], formData: formData[key] || [], required: ((_b = uiSchema[key]) === null || _b === void 0 ? void 0 : _b["ui:required"]) || false, onChange: this.onChange(key), onBlur: this.props.onBlur, onFocus: this.props.onFocus, disabled: this.props.disabled, readonly: this.props.readonly, name: this.props.name })));
122
122
  }))));
123
123
  }
124
124
  };
@@ -0,0 +1,54 @@
1
+ import * as React from "react";
2
+ import { ByLang, FormContext } from "../../LajiForm";
3
+ import { NamedPlace } from "@luomus/laji-schema";
4
+ import memoize from "memoizee";
5
+ declare type Props = {
6
+ places: NamedPlace[];
7
+ failed?: boolean;
8
+ formContext: FormContext;
9
+ onSelected: (place: NamedPlace) => void;
10
+ onDeleted: (place: NamedPlace, callback: () => void) => void;
11
+ };
12
+ declare type State = {
13
+ deleting?: boolean;
14
+ popupIdx?: number;
15
+ };
16
+ export declare class NamedPlaceChooser extends React.Component<Props, State> {
17
+ static contextType: React.Context<import("../../../ReactContext").ContextProps>;
18
+ popupRef: React.RefObject<{
19
+ elem: HTMLElement;
20
+ button: HTMLElement;
21
+ }>;
22
+ popupContainerRef: React.RefObject<HTMLDivElement>;
23
+ mapRef: React.RefObject<any>;
24
+ idxToLayer?: Record<string, any>;
25
+ geometryCollectionData?: {
26
+ geoData: any;
27
+ };
28
+ constructor(props: Props);
29
+ onPlaceSelected: (place: NamedPlace) => void;
30
+ onPlaceDeleted: (place: NamedPlace) => void;
31
+ onSelectChange: (idx: number | undefined) => void;
32
+ componentDidUpdate(_: Props, prevState: State): void;
33
+ getFeatureStyle: (data: any) => {
34
+ color: string;
35
+ fillColor: string;
36
+ };
37
+ getPopup: ({ feature }: any, givePopupToLajiMap: (element: HTMLElement) => void) => void;
38
+ onPopupClose: () => void;
39
+ getEnumOptions: ((places: NamedPlace[], translations: ByLang) => {
40
+ placeholder: string;
41
+ enumOptions: {
42
+ value: number;
43
+ label: string;
44
+ }[];
45
+ }) & memoize.Memoized<(places: NamedPlace[], translations: ByLang) => {
46
+ placeholder: string;
47
+ enumOptions: {
48
+ value: number;
49
+ label: string;
50
+ }[];
51
+ }>;
52
+ render(): JSX.Element;
53
+ }
54
+ export {};
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ var __importDefault = (this && this.__importDefault) || function (mod) {
22
+ return (mod && mod.__esModule) ? mod : { "default": mod };
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.NamedPlaceChooser = void 0;
26
+ const React = __importStar(require("react"));
27
+ const react_dom_1 = require("react-dom");
28
+ const react_spinner_1 = __importDefault(require("react-spinner"));
29
+ const ReactContext_1 = __importDefault(require("../../../ReactContext"));
30
+ const MapArrayField_1 = require("../MapArrayField");
31
+ const globals_1 = require("@luomus/laji-map/lib/globals");
32
+ const SelectWidget_1 = require("../../widgets/SelectWidget");
33
+ const Popup_1 = require("./Popup");
34
+ const memoizee_1 = __importDefault(require("memoizee"));
35
+ class NamedPlaceChooser extends React.Component {
36
+ constructor(props) {
37
+ super(props);
38
+ this.popupRef = React.createRef();
39
+ this.popupContainerRef = React.createRef();
40
+ this.mapRef = React.createRef();
41
+ this.onPlaceSelected = (place) => {
42
+ this.props.onSelected(place);
43
+ };
44
+ this.onPlaceDeleted = (place) => {
45
+ const onDelete = () => {
46
+ this.mapRef.current.map.map.closePopup();
47
+ this.setState({ deleting: false, popupIdx: undefined });
48
+ };
49
+ this.setState({ deleting: true });
50
+ this.props.onDeleted(place, onDelete);
51
+ };
52
+ this.onSelectChange = (idx) => {
53
+ if (idx === undefined) {
54
+ return;
55
+ }
56
+ const { map } = this.mapRef.current;
57
+ const layers = this.idxToLayer[idx];
58
+ const [layer] = layers;
59
+ const bounds = map.getBoundsForLayers(layers);
60
+ const center = bounds.getCenter();
61
+ map.fitBounds(bounds, { animate: false });
62
+ layer.fire("click", { latlng: center });
63
+ };
64
+ this.getFeatureStyle = (data) => {
65
+ const { feature = {} } = data || {};
66
+ function getColor(idx) {
67
+ const r = globals_1.NORMAL_COLOR.substring(1, 3);
68
+ const g = globals_1.NORMAL_COLOR.substring(3, 5);
69
+ const b = globals_1.NORMAL_COLOR.substring(5, 7);
70
+ return [r, g, b].reduce((rgb, hex) => {
71
+ const decimal = parseInt(hex, 16);
72
+ const amount = 40;
73
+ const _decimal = (idx % 2) ? decimal : Math.min(decimal + amount, 255);
74
+ return rgb + _decimal.toString(16);
75
+ }, "#");
76
+ }
77
+ const { idx } = feature.properties || {};
78
+ const color = idx === this.state.popupIdx ? globals_1.ACTIVE_COLOR : getColor(idx);
79
+ return { color, fillColor: color };
80
+ };
81
+ this.getPopup = ({ feature }, givePopupToLajiMap) => {
82
+ const { elem, button } = this.popupRef.current;
83
+ const { idx } = feature.properties;
84
+ this.setState({ popupIdx: idx });
85
+ givePopupToLajiMap(elem);
86
+ this.props.formContext.setTimeout(() => react_dom_1.findDOMNode(button).focus());
87
+ };
88
+ this.onPopupClose = () => {
89
+ this.popupContainerRef.current.appendChild(react_dom_1.findDOMNode(this.popupRef.current.elem));
90
+ };
91
+ this.getEnumOptions = memoizee_1.default((places, translations) => ({
92
+ placeholder: `${translations.SelectPlaceFromList}...`,
93
+ enumOptions: (places || []).map((place, idx) => {
94
+ return { value: idx, label: place.name };
95
+ })
96
+ }));
97
+ this.state = {};
98
+ }
99
+ componentDidUpdate(_, prevState) {
100
+ const { map } = this.mapRef.current;
101
+ this.idxToLayer = map.data.reduce((idxToLayer, item) => {
102
+ const layerGroup = item.group;
103
+ layerGroup.eachLayer((layer) => {
104
+ if (!idxToLayer[layer.feature.properties.idx]) {
105
+ idxToLayer[layer.feature.properties.idx] = [];
106
+ }
107
+ idxToLayer[layer.feature.properties.idx].push(layer);
108
+ });
109
+ return idxToLayer;
110
+ }, {});
111
+ if (this.state.popupIdx !== prevState.popupIdx) {
112
+ const prevLayers = this.idxToLayer[prevState.popupIdx] || [];
113
+ const layers = this.idxToLayer[this.state.popupIdx] || [];
114
+ [prevLayers, layers].forEach(layers => {
115
+ layers.forEach((layer) => {
116
+ if (layer) {
117
+ map.setLayerStyle(layer, this.getFeatureStyle({ feature: layer.feature }));
118
+ }
119
+ });
120
+ });
121
+ }
122
+ }
123
+ render() {
124
+ const { places, failed, formContext: { translations } } = this.props;
125
+ const { Alert } = this.context.theme;
126
+ if (failed) {
127
+ return React.createElement(Alert, { variant: "danger" }, `${translations.NamedPlacesFetchFail} ${translations.TryAgainLater}`);
128
+ }
129
+ else {
130
+ let pointer = 1;
131
+ const data = (places || []).reduce((data, place, i) => {
132
+ const { geometry } = place;
133
+ let isCollection = false;
134
+ if (geometry.type === "GeometryCollection") {
135
+ isCollection = true;
136
+ }
137
+ if (isCollection) {
138
+ data[pointer] = {
139
+ geoData: { type: "FeatureCollection", features: geometry.geometries.map((geom) => { return { type: "Feature", geometry: geom, properties: { idx: i } }; }) },
140
+ getFeatureStyle: this.getFeatureStyle,
141
+ getPopup: this.getPopup,
142
+ highlightOnHover: true
143
+ };
144
+ pointer++;
145
+ }
146
+ else {
147
+ if (!data[0])
148
+ data[0] = {
149
+ geoData: { type: "FeatureCollection", features: [] },
150
+ getFeatureStyle: this.getFeatureStyle,
151
+ getPopup: this.getPopup,
152
+ cluster: true,
153
+ highlightOnHover: true
154
+ };
155
+ data[0].geoData.features.push({ type: "Feature", geometry, properties: { idx: i } });
156
+ }
157
+ return data;
158
+ }, []);
159
+ return (React.createElement("div", { style: { height: "inherit" } },
160
+ React.createElement(SelectWidget_1.SearchableDrowndown, { value: this.state.popupIdx, disabled: !places, options: this.getEnumOptions(places, translations), onChange: this.onSelectChange, selectOnChange: false, includeEmpty: true, id: "named-place-chooser-select", formContext: this.props.formContext }),
161
+ React.createElement(MapArrayField_1.Map, { ref: this.mapRef, data: data, markerPopupOffset: 45, featurePopupOffset: 5, controls: { draw: false }, lang: this.props.formContext.lang, bodyAsDialogRoot: false, formContext: this.props.formContext, onPopupClose: this.onPopupClose }),
162
+ (!places) ? React.createElement(react_spinner_1.default, null) : null,
163
+ React.createElement("div", { style: { display: "none" }, ref: this.popupContainerRef },
164
+ React.createElement(Popup_1.Popup, { ref: this.popupRef, place: (places || [])[this.state.popupIdx], onPlaceSelected: this.onPlaceSelected, onPlaceDeleted: this.onPlaceDeleted, deleting: this.state.deleting, translations: translations }))));
165
+ }
166
+ }
167
+ }
168
+ exports.NamedPlaceChooser = NamedPlaceChooser;
169
+ NamedPlaceChooser.contextType = ReactContext_1.default;
@@ -0,0 +1,71 @@
1
+ import * as React from "react";
2
+ import { FieldProps, JSONSchemaArray, JSONSchemaObject } from "../../../types";
3
+ import { NamedPlace } from "@luomus/laji-schema";
4
+ declare type Props = FieldProps<NamedPlace, JSONSchemaObject | JSONSchemaArray<JSONSchemaObject>>;
5
+ declare type State = {
6
+ show?: boolean;
7
+ failed?: string;
8
+ buttonDefinition?: any;
9
+ places?: NamedPlace[];
10
+ };
11
+ /** Compatible only with gatherings array and gathering object */
12
+ export default class NamedPlaceChooserField extends React.Component<Props, State> {
13
+ static contextType: React.Context<import("../../../ReactContext").ContextProps>;
14
+ removeIds: Record<string, boolean>;
15
+ mounted: boolean;
16
+ state: State;
17
+ getUiSchema: (props: Props, buttonDefinition: any) => import("../../../types").UiSchema<any> | {
18
+ "ui:options": any;
19
+ "ui:ArrayFieldTemplate"?: React.ComponentType<import("@rjsf/utils").ArrayFieldTemplateProps<any, any, import("../../LajiForm").FormContext>> | undefined;
20
+ "ui:ArrayFieldDescriptionTemplate"?: React.ComponentType<import("@rjsf/utils").ArrayFieldDescriptionProps<any, any, import("../../LajiForm").FormContext>> | undefined;
21
+ "ui:ArrayFieldItemTemplate"?: React.ComponentType<import("@rjsf/utils").ArrayFieldTemplateItemType<any, any, import("../../LajiForm").FormContext>> | undefined;
22
+ "ui:ArrayFieldTitleTemplate"?: React.ComponentType<import("@rjsf/utils").ArrayFieldTitleProps<any, any, import("../../LajiForm").FormContext>> | undefined;
23
+ "ui:BaseInputTemplate"?: React.ComponentType<import("@rjsf/utils").WidgetProps<any, any, import("../../LajiForm").FormContext>> | undefined;
24
+ "ui:DescriptionFieldTemplate"?: React.ComponentType<import("@rjsf/utils").DescriptionFieldProps<any, any, import("../../LajiForm").FormContext>> | undefined;
25
+ "ui:ErrorListTemplate"?: React.ComponentType<import("@rjsf/utils").ErrorListProps<any, any, import("../../LajiForm").FormContext>> | undefined;
26
+ "ui:FieldErrorTemplate"?: React.ComponentType<import("@rjsf/utils").FieldErrorProps<any, any, import("../../LajiForm").FormContext>> | undefined;
27
+ "ui:FieldHelpTemplate"?: React.ComponentType<import("@rjsf/utils").FieldHelpProps<any, any, import("../../LajiForm").FormContext>> | undefined;
28
+ "ui:FieldTemplate"?: React.ComponentType<import("@rjsf/utils").FieldTemplateProps<any, any, import("../../LajiForm").FormContext>> | undefined;
29
+ "ui:ObjectFieldTemplate"?: React.ComponentType<import("@rjsf/utils").ObjectFieldTemplateProps<any, any, import("../../LajiForm").FormContext>> | undefined;
30
+ "ui:TitleFieldTemplate"?: React.ComponentType<import("@rjsf/utils").TitleFieldProps<any, any, import("../../LajiForm").FormContext>> | undefined;
31
+ "ui:UnsupportedFieldTemplate"?: React.ComponentType<import("@rjsf/utils").UnsupportedFieldProps<any, any, import("../../LajiForm").FormContext>> | undefined;
32
+ "ui:WrapIfAdditionalTemplate"?: React.ComponentType<import("@rjsf/utils").WrapIfAdditionalTemplateProps<any, any, import("../../LajiForm").FormContext>> | undefined;
33
+ "ui:classNames"?: string | undefined;
34
+ "ui:style"?: React.StyleHTMLAttributes<any> | undefined;
35
+ "ui:title"?: string | undefined;
36
+ "ui:description"?: string | undefined;
37
+ "ui:placeholder"?: string | undefined;
38
+ "ui:help"?: string | undefined;
39
+ "ui:autofocus"?: boolean | undefined;
40
+ "ui:autocomplete"?: string | undefined;
41
+ "ui:disabled"?: boolean | undefined;
42
+ "ui:emptyValue"?: any;
43
+ "ui:enumDisabled"?: (string | number | boolean)[] | undefined;
44
+ "ui:hideError"?: boolean | undefined;
45
+ "ui:readonly"?: boolean | undefined;
46
+ "ui:order"?: string[] | undefined;
47
+ "ui:addable"?: boolean | undefined;
48
+ "ui:orderable"?: boolean | undefined;
49
+ "ui:removable"?: boolean | undefined;
50
+ "ui:inline"?: boolean | undefined;
51
+ "ui:inputType"?: string | undefined;
52
+ "ui:label"?: boolean | undefined;
53
+ "ui:rows"?: number | undefined;
54
+ "ui:submitButtonOptions"?: import("@rjsf/utils").UISchemaSubmitButtonOptions | undefined;
55
+ "ui:widget"?: string | import("@rjsf/utils").Widget<any, any, import("../../LajiForm").FormContext> | undefined;
56
+ "ui:duplicateKeySuffixSeparator"?: string | undefined;
57
+ "ui:rootFieldId"?: string | undefined;
58
+ "ui:field"?: string | import("@rjsf/utils").Field<any, any, import("../../LajiForm").FormContext> | undefined;
59
+ "ui:fieldReplacesAnyOrOneOf"?: boolean | undefined;
60
+ };
61
+ isGatheringsArray: (schema: JSONSchemaObject | JSONSchemaArray<JSONSchemaObject>) => schema is JSONSchemaArray<JSONSchemaObject, never>;
62
+ onPlaceSelected: (place: NamedPlace) => void;
63
+ onPlaceDeleted: (place: NamedPlace, success: () => void) => void;
64
+ onButtonClick: () => () => void;
65
+ updatePlaces: () => void;
66
+ componentDidMount(): void;
67
+ componentWillUnmount(): void;
68
+ onHide: () => void;
69
+ render(): JSX.Element;
70
+ }
71
+ export {};
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ var __importDefault = (this && this.__importDefault) || function (mod) {
22
+ return (mod && mod.__esModule) ? mod : { "default": mod };
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ const React = __importStar(require("react"));
26
+ const ReactContext_1 = __importDefault(require("../../../ReactContext"));
27
+ const utils_1 = require("../../../utils");
28
+ const Context_1 = __importDefault(require("../../../Context"));
29
+ const NamedPlaceChooser_1 = require("./NamedPlaceChooser");
30
+ const PLACE_WHITELIST = [
31
+ "geometry",
32
+ "country",
33
+ "administrativeProvince",
34
+ "biologicalProvince",
35
+ "municipality",
36
+ "locality",
37
+ "localityDescription",
38
+ "habitat",
39
+ "habitatDescription"
40
+ ];
41
+ const PLACES_FETCH_FAIL = "PLACES_FETCH_FAIL";
42
+ const PLACE_USE_FAIL = "PLACE_USE_FAIL";
43
+ const PLACE_DELETE_FAIL = "PLACE_DELETE_FAIL";
44
+ /** Compatible only with gatherings array and gathering object */
45
+ class NamedPlaceChooserField extends React.Component {
46
+ constructor() {
47
+ super(...arguments);
48
+ this.removeIds = {};
49
+ this.mounted = false;
50
+ this.state = {};
51
+ this.getUiSchema = (props, buttonDefinition) => {
52
+ if (buttonDefinition) {
53
+ buttonDefinition = Object.assign(Object.assign({}, buttonDefinition), { label: props.formContext.translations.ChooseFromNamedPlace });
54
+ const innerUiSchema = utils_1.getInnerUiSchema(props.uiSchema);
55
+ const options = utils_1.getUiOptions(innerUiSchema);
56
+ return Object.assign(Object.assign({}, innerUiSchema), { "ui:options": Object.assign(Object.assign({}, options), { buttons: [
57
+ buttonDefinition,
58
+ ...(options.buttons || [])
59
+ ] }) });
60
+ }
61
+ else {
62
+ return utils_1.getInnerUiSchema(props.uiSchema);
63
+ }
64
+ };
65
+ this.isGatheringsArray = (schema) => schema.type === "array";
66
+ this.onPlaceSelected = (place) => {
67
+ const getGathering = (schema) => {
68
+ let gathering = utils_1.getDefaultFormState(schema);
69
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
70
+ const placeGathering = place.prepopulatedDocument.gatherings[0];
71
+ PLACE_WHITELIST.forEach(prop => {
72
+ if (prop in placeGathering && prop in schema.properties) {
73
+ gathering[prop] = placeGathering[prop];
74
+ }
75
+ });
76
+ gathering.namedPlaceID = place.id;
77
+ const tmpIdTree = this.props.formContext.services.ids.getRelativeTmpIdTree(this.props.idSchema.$id);
78
+ const [withLajiFormIds] = utils_1.addLajiFormIds(gathering, tmpIdTree, false);
79
+ return withLajiFormIds;
80
+ };
81
+ try {
82
+ let targetId, gathering, newFormData, zoomToData;
83
+ const { schema } = this.props;
84
+ if (this.isGatheringsArray(schema)) {
85
+ gathering = getGathering(schema.items);
86
+ newFormData = [
87
+ ...(this.props.formData || []),
88
+ gathering
89
+ ];
90
+ this.setState({ show: false });
91
+ targetId = this.props.idSchema.$id;
92
+ this.props.formContext.services.customEvents.send(targetId, "activeIdx", (this.props.formData || []).length);
93
+ }
94
+ else { // gathering object
95
+ gathering = getGathering(schema);
96
+ gathering.namedPlaceID = place.id;
97
+ newFormData = Object.assign(Object.assign({}, this.props.formData), gathering);
98
+ this.setState({ show: false });
99
+ const splits = this.props.idSchema.$id.split("_");
100
+ splits.pop();
101
+ targetId = splits.join("_");
102
+ zoomToData = true;
103
+ }
104
+ this.props.onChange(newFormData);
105
+ if (zoomToData)
106
+ this.props.formContext.services.customEvents.send(targetId, "zoomToData", undefined);
107
+ }
108
+ catch (e) {
109
+ this.setState({ failed: PLACE_USE_FAIL });
110
+ }
111
+ };
112
+ this.onPlaceDeleted = (place, success) => {
113
+ this.props.formContext.apiClient.fetchRaw(`/named-places/${place.id}`, undefined, { method: "DELETE" }).then(response => {
114
+ if (response.status < 400) {
115
+ // It takes a while for API to remove the place, so we remove it locally and then invalidate again after some time.
116
+ this.removeIds[place.id] = true;
117
+ this.props.formContext.apiClient.invalidateCachePath("/named-places");
118
+ setTimeout(() => this.props.formContext.apiClient.invalidateCachePath("/named-places"), 2000);
119
+ success();
120
+ }
121
+ }).catch(() => {
122
+ this.setState({ failed: PLACE_DELETE_FAIL });
123
+ this.props.formContext.notifier.error(this.props.formContext.translations.PlaceRemovalFailed);
124
+ });
125
+ };
126
+ this.onButtonClick = () => () => {
127
+ this.setState({ show: true });
128
+ };
129
+ this.updatePlaces = () => {
130
+ this.props.formContext.apiClient.fetchCached("/named-places", { includePublic: false, pageSize: 100000 }).then(response => {
131
+ var _a;
132
+ if (!this.mounted)
133
+ return;
134
+ const state = { places: response.results.filter(p => !this.removeIds[p.id]).sort((a, b) => {
135
+ if (a.name < b.name)
136
+ return -1;
137
+ if (a.name > b.name)
138
+ return 1;
139
+ return 0;
140
+ }) };
141
+ if (!((_a = response.results) === null || _a === void 0 ? void 0 : _a.length)) {
142
+ return;
143
+ }
144
+ const buttonDefinition = {
145
+ fn: this.onButtonClick,
146
+ fnName: "addNamedPlace",
147
+ glyph: "map-marker",
148
+ label: this.props.formContext.translations.ChooseFromNamedPlace,
149
+ id: this.props.idSchema.$id,
150
+ changesFormData: true,
151
+ variant: "primary"
152
+ };
153
+ if (this.isGatheringsArray(this.props.schema)) {
154
+ buttonDefinition.rules = { canAdd: true };
155
+ }
156
+ else {
157
+ buttonDefinition.position = "top";
158
+ }
159
+ state.buttonDefinition = buttonDefinition;
160
+ this.setState(state);
161
+ }).catch(() => {
162
+ this.setState({ failed: PLACES_FETCH_FAIL });
163
+ });
164
+ };
165
+ this.onHide = () => this.setState({ show: false });
166
+ }
167
+ componentDidMount() {
168
+ this.mounted = true;
169
+ this.updatePlaces();
170
+ this.props.formContext.apiClient.onCachePathInvalidation("/named-places", this.updatePlaces);
171
+ }
172
+ componentWillUnmount() {
173
+ this.mounted = false;
174
+ this.props.formContext.apiClient.removeOnCachePathInvalidation("/named-places", this.updatePlaces);
175
+ }
176
+ render() {
177
+ const { registry: { fields: { SchemaField } }, formContext } = this.props;
178
+ const { translations } = formContext;
179
+ const { failed } = this.state;
180
+ const { Modal, Alert } = this.context.theme;
181
+ return React.createElement(React.Fragment, null,
182
+ React.createElement(SchemaField, Object.assign({}, this.props, { uiSchema: this.getUiSchema(this.props, this.state.buttonDefinition) })),
183
+ this.state.places && this.state.show ? (React.createElement(Modal, { dialogClassName: "laji-form map-dialog named-place-chooser-modal", show: true, onHide: this.onHide },
184
+ React.createElement(Modal.Header, { closeButton: true }, translations.ChooseNamedPlace),
185
+ React.createElement(Modal.Body, null,
186
+ failed === PLACE_USE_FAIL && React.createElement(Alert, { variant: "danger" }, translations.NamedPlacesUseFail),
187
+ failed === PLACES_FETCH_FAIL && React.createElement(Alert, { variant: "danger" }, translations.NamedPlacesFetchFail),
188
+ React.createElement(NamedPlaceChooser_1.NamedPlaceChooser, { places: this.state.places, failed: failed === PLACES_FETCH_FAIL ? true : false, formContext: formContext, onSelected: this.onPlaceSelected, onDeleted: this.onPlaceDeleted })))) : null);
189
+ }
190
+ }
191
+ exports.default = NamedPlaceChooserField;
192
+ NamedPlaceChooserField.contextType = ReactContext_1.default;
193
+ Context_1.default("SCHEMA_FIELD_WRAPPERS").NamedPlaceChooserField = true;
@@ -0,0 +1,12 @@
1
+ import * as React from "react";
2
+ import { NamedPlace } from "@luomus/laji-schema";
3
+ import { FormContext } from "src/components/LajiForm";
4
+ declare type Props = {
5
+ onPlaceSelected: (place: NamedPlace) => void;
6
+ onPlaceDeleted: (place: NamedPlace) => void;
7
+ place: NamedPlace;
8
+ translations: FormContext["translations"];
9
+ deleting?: boolean;
10
+ };
11
+ export declare const Popup: React.ForwardRefExoticComponent<Props & React.RefAttributes<any>>;
12
+ export {};
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ var __importDefault = (this && this.__importDefault) || function (mod) {
22
+ return (mod && mod.__esModule) ? mod : { "default": mod };
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.Popup = void 0;
26
+ const React = __importStar(require("react"));
27
+ const react_1 = require("react");
28
+ const react_spinner_1 = __importDefault(require("react-spinner"));
29
+ const utils_1 = require("../../../utils");
30
+ const components_1 = require("../../../components/components");
31
+ exports.Popup = react_1.forwardRef((props, ref) => {
32
+ const { onPlaceSelected, onPlaceDeleted, place, translations, deleting } = props;
33
+ const _onPlaceSelected = react_1.useCallback(() => {
34
+ onPlaceSelected(place);
35
+ }, [onPlaceSelected, place]);
36
+ const _onPlaceDeleted = react_1.useCallback(() => {
37
+ onPlaceDeleted(place);
38
+ }, [onPlaceDeleted, place]);
39
+ const containerRef = react_1.useRef(null);
40
+ const buttonRef = react_1.useRef(null);
41
+ react_1.useImperativeHandle(ref, () => ({
42
+ elem: containerRef.current,
43
+ button: buttonRef.current,
44
+ }));
45
+ return (React.createElement("div", { className: "named-place-popup", ref: containerRef },
46
+ !place
47
+ ? React.createElement(react_spinner_1.default, null)
48
+ : React.createElement("table", null,
49
+ React.createElement("tbody", null, [
50
+ ["Name", "name"],
51
+ ["Notes", "notes"]
52
+ ].reduce((fieldset, [translationKey, fieldName], i) => {
53
+ if (!utils_1.isEmptyString(place[fieldName]))
54
+ fieldset.push(React.createElement("tr", { key: i },
55
+ React.createElement("td", null,
56
+ React.createElement("b", null,
57
+ translations[translationKey],
58
+ ": ")),
59
+ React.createElement("td", null, place[fieldName])));
60
+ return fieldset;
61
+ }, []))),
62
+ React.createElement(components_1.Button, { block: true, disabled: !place, ref: buttonRef, onClick: _onPlaceSelected }, translations.UseThisPlace),
63
+ React.createElement(components_1.DeleteButton, { block: true, onClick: _onPlaceDeleted, disabled: deleting, glyphButton: false, confirm: true, confirmStyle: "browser", translations: translations },
64
+ translations.Remove,
65
+ " ",
66
+ deleting && React.createElement(react_spinner_1.default, null))));
67
+ });
@@ -0,0 +1 @@
1
+ export { default } from "./NamedPlaceChooserField";
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = void 0;
7
+ var NamedPlaceChooserField_1 = require("./NamedPlaceChooserField");
8
+ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(NamedPlaceChooserField_1).default; } });