@luomus/laji-form 15.1.68 → 15.1.69

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 (31) hide show
  1. package/dist/laji-form.js +1 -1
  2. package/lib/ApiClient.d.ts +21 -66
  3. package/lib/ApiClient.js +68 -174
  4. package/lib/components/LajiForm.js +1 -1
  5. package/lib/components/fields/AnnotationField.js +22 -26
  6. package/lib/components/fields/AudioArrayField.js +5 -18
  7. package/lib/components/fields/AutosuggestField.d.ts +2 -2
  8. package/lib/components/fields/AutosuggestField.js +4 -4
  9. package/lib/components/fields/EnumRangeArrayField.js +1 -1
  10. package/lib/components/fields/GeocoderField.js +9 -2
  11. package/lib/components/fields/ImageArrayField.d.ts +2 -2
  12. package/lib/components/fields/ImageArrayField.js +112 -82
  13. package/lib/components/fields/MapArrayField.js +5 -13
  14. package/lib/components/fields/MapField.d.ts +1 -1
  15. package/lib/components/fields/MapField.js +5 -13
  16. package/lib/components/fields/NamedPlaceChooserField/NamedPlaceChooser.d.ts +1 -2
  17. package/lib/components/fields/NamedPlaceChooserField/NamedPlaceChooserField.d.ts +4 -9
  18. package/lib/components/fields/NamedPlaceChooserField/NamedPlaceChooserField.js +51 -51
  19. package/lib/components/fields/NamedPlaceChooserField/Popup.d.ts +1 -2
  20. package/lib/components/fields/NamedPlaceSaverField.js +18 -22
  21. package/lib/components/fields/ScopeField.js +1 -1
  22. package/lib/components/fields/SingleActiveArrayField.js +2 -2
  23. package/lib/components/fields/SortArrayField.js +1 -1
  24. package/lib/components/fields/UnitCountShorthandField.js +1 -1
  25. package/lib/components/fields/UnitListShorthandArrayField.js +2 -2
  26. package/lib/components/fields/UnitShorthandField.js +18 -14
  27. package/lib/components/widgets/AutosuggestWidget.js +66 -79
  28. package/lib/components/widgets/InformalTaxonGroupChooserWidget.js +1 -1
  29. package/lib/components/widgets/InputWithDefaultValueButtonWidget.js +2 -1
  30. package/lib/validation.js +1 -1
  31. package/package.json +3 -5
@@ -911,13 +911,13 @@ const headerFormatters = {
911
911
  this.fetch = (props) => {
912
912
  const { namedPlaceID } = (props.that.props.formData || {})[props.idx] || {};
913
913
  if (namedPlaceID)
914
- props.that.props.formContext.apiClient.get("/named-places/{id}", { path: { id: namedPlaceID } }).then(response => {
914
+ props.that.props.formContext.apiClient.fetchCached(`/named-places/${namedPlaceID}`, undefined, { failSilently: true }).then(response => {
915
915
  if (this.mounted && response.name !== this.state.name)
916
916
  this.setState({
917
917
  namedPlaceID,
918
918
  name: response.name
919
919
  });
920
- }).catch(() => { });
920
+ });
921
921
  };
922
922
  this.state = {};
923
923
  }
@@ -69,7 +69,7 @@ class TaxonomicComparer extends Comparer {
69
69
  }
70
70
  initialize() {
71
71
  return __awaiter(this, void 0, void 0, function* () {
72
- this.idToIdx = (yield this.formContext.apiClient.get("/taxa", { query: Object.assign(Object.assign({}, this.options.query), { pageSize: 10000, selectedFields: "id" }) }))
72
+ this.idToIdx = (yield this.formContext.apiClient.fetchCached("/taxa", Object.assign(Object.assign({}, this.options.query), { pageSize: 10000, selectedFields: "id" })))
73
73
  .results.reduce((idToIdx, { id }, idx) => {
74
74
  idToIdx[id] = idx;
75
75
  return idToIdx;
@@ -82,7 +82,7 @@ let UnitCountShorthandField = class UnitCountShorthandField extends React.Compon
82
82
  resolve({ success: undefined });
83
83
  return;
84
84
  }
85
- apiClient.get("/shorthand/unit/water-bird-pair-count", { query: { query: value, taxonID: taxonId } }).then(suggestion => {
85
+ apiClient.fetchCached("/autocomplete/pairCount", { q: value, taxonID: taxonId }).then(suggestion => {
86
86
  if (timestamp !== this.promiseTimestamp) {
87
87
  reject();
88
88
  return;
@@ -69,8 +69,8 @@ let UnitListShorthandArrayField = class UnitListShorthandArrayField extends Reac
69
69
  this.onHide();
70
70
  const { translations, notifier, apiClient } = this.props.formContext;
71
71
  this.props.formContext.services.blocker.push();
72
- apiClient.get("/shorthand/unit/list", { query: { query: value } }).then(({ results, nonMatchingCount }) => {
73
- const units = results.map(unit => {
72
+ apiClient.fetch("/autocomplete/unit", { q: value, list: true, includePayload: true }).then(({ payload: { units, nonMatchingCount } }) => {
73
+ units = units.map(unit => {
74
74
  unit = (0, utils_1.getDefaultFormState)(this.props.schema.items, unit);
75
75
  unit = (0, utils_1.bringRemoteFormData)(unit, this.props.formContext);
76
76
  unit = (0, utils_1.assignUUID)(unit);
@@ -51,6 +51,7 @@ const ReactContext_1 = __importDefault(require("../../ReactContext"));
51
51
  const components_1 = require("../components");
52
52
  const AutosuggestWidget_1 = require("../widgets/AutosuggestWidget");
53
53
  const ArrayFieldTemplate_1 = require("../templates/ArrayFieldTemplate");
54
+ const LINE_TRANSECT_IDS = ["MHL.1162", "MHL.27", "MHL.28"];
54
55
  let UnitShorthandField = class UnitShorthandField extends React.Component {
55
56
  constructor(props) {
56
57
  super(props);
@@ -124,13 +125,13 @@ let UnitShorthandField = class UnitShorthandField extends React.Component {
124
125
  render() {
125
126
  const { uiSchema, formContext, disabled, readonly } = this.props;
126
127
  const { SchemaField } = this.props.registry.fields;
127
- const { shorthandField, lineTransect } = (0, utils_1.getUiOptions)(this.props.uiSchema);
128
+ const shorthandFieldName = (0, utils_1.getUiOptions)(this.props.uiSchema).shorthandField;
128
129
  const toggleButton = this.getToggleButton();
129
130
  const tailUiSchema = (0, utils_1.getNestedTailUiSchema)(uiSchema);
130
- let help = tailUiSchema && tailUiSchema[shorthandField] && tailUiSchema[shorthandField]["ui:belowHelp"];
131
- const uiSchemaWithoutHelp = (0, utils_1.isEmptyString)(help) ? uiSchema : (0, utils_1.updateTailUiSchema)(uiSchema, { [shorthandField]: { "ui:belowHelp": { $set: undefined } } });
132
- const id = (shorthandField && this.props.idSchema[shorthandField]) ?
133
- this.props.idSchema[shorthandField].$id :
131
+ let help = tailUiSchema && tailUiSchema[shorthandFieldName] && tailUiSchema[shorthandFieldName]["ui:belowHelp"];
132
+ const uiSchemaWithoutHelp = (0, utils_1.isEmptyString)(help) ? uiSchema : (0, utils_1.updateTailUiSchema)(uiSchema, { [shorthandFieldName]: { "ui:belowHelp": { $set: undefined } } });
133
+ const id = (shorthandFieldName && this.props.idSchema[shorthandFieldName]) ?
134
+ this.props.idSchema[shorthandFieldName].$id :
134
135
  `${this.props.idSchema.$id}_shortHandField`;
135
136
  let innerUiSchema = undefined;
136
137
  if (this.state.showSchema) {
@@ -139,7 +140,7 @@ let UnitShorthandField = class UnitShorthandField extends React.Component {
139
140
  innerUiSchema = Object.assign(Object.assign({}, innerUiSchema), { "ui:options": Object.assign(Object.assign({}, innerOptions), { buttons: [...(innerOptions.buttons || []), toggleButton] }) });
140
141
  }
141
142
  return !this.state.showSchema ? (React.createElement("div", { className: "laji-form-field-template-item", id: `_laji-form_${id}` },
142
- React.createElement(CodeReader, { translations: this.props.formContext.translations, onChange: this.onCodeChange, value: this.props.formData[shorthandField], formID: (0, utils_1.getUiOptions)(this.props.uiSchema).formID || formContext.formID || formContext.uiSchemaContext.formID, help: help, id: id, formContext: formContext, disabled: disabled, readonly: readonly, lineTransect: lineTransect, className: "laji-form-field-template-schema" }),
143
+ React.createElement(CodeReader, { translations: this.props.formContext.translations, onChange: this.onCodeChange, value: this.props.formData[shorthandFieldName], formID: (0, utils_1.getUiOptions)(this.props.uiSchema).formID || formContext.formID || formContext.uiSchemaContext.formID, help: help, id: id, formContext: formContext, disabled: disabled, readonly: readonly, className: "laji-form-field-template-schema" }),
143
144
  React.createElement("div", { className: "laji-form-field-template-buttons" }, (0, ArrayFieldTemplate_1.getButton)(toggleButton)))) : (React.createElement(SchemaField, Object.assign({}, this.props, { uiSchema: innerUiSchema })));
144
145
  }
145
146
  };
@@ -184,14 +185,14 @@ let CodeReader = class CodeReader extends React.Component {
184
185
  this.onAutosuggestChange = (formData) => {
185
186
  this.props.onChange(formData);
186
187
  };
187
- this.onSuggestionSelected = ({ unit }) => {
188
+ this.onSuggestionSelected = ({ payload: { unit } }) => {
188
189
  const { formContext } = this.props;
189
190
  unit = (0, utils_1.bringRemoteFormData)(unit, formContext);
190
191
  this.props.onChange(unit);
191
192
  };
192
193
  this.renderSuggestion = (suggestion) => {
193
194
  const { translations } = this.props;
194
- return suggestion.isNonMatching
195
+ return suggestion.payload.isNonMatching
195
196
  ? React.createElement("span", { className: "text-muted" },
196
197
  suggestion.value,
197
198
  " ",
@@ -211,8 +212,8 @@ let CodeReader = class CodeReader extends React.Component {
211
212
  }
212
213
  else if (value.length >= 3) {
213
214
  this.mounted && this.setState({ loading: true });
214
- this.apiClient.get("/shorthand/unit/line-transect", { query: { query: value } }).then(response => {
215
- this.props.onChange(response.unit);
215
+ this.apiClient.fetchCached("/autocomplete/unit", { q: value, formID: this.props.formID, includePayload: true }).then(response => {
216
+ this.props.onChange(response.payload.unit);
216
217
  }).catch(() => {
217
218
  this.mounted && this.setState({ failed: true, loading: false });
218
219
  });
@@ -229,15 +230,18 @@ let CodeReader = class CodeReader extends React.Component {
229
230
  this.mounted = false;
230
231
  }
231
232
  render() {
232
- const { translations, readonly, disabled, lineTransect } = this.props;
233
+ const { translations, readonly, disabled } = this.props;
233
234
  let validationState = null;
234
235
  if (this.state.failed === true)
235
236
  validationState = "warning";
236
237
  else if (!(0, utils_1.isEmptyString)(this.props.value) && this.props.value === this.state.value)
237
238
  validationState = "success";
238
- const { formContext } = this.props;
239
- const inputElem = lineTransect ? (React.createElement(components_1.FetcherInput, { id: this.props.id, loading: this.state.loading, value: this.state.value, validationState: validationState, onChange: this.onFetcherInputChange, onBlur: this.getCode, onKeyDown: this.onKeyDown, readonly: readonly, disabled: disabled })) : (React.createElement("div", { className: "unit-shorthand" },
240
- React.createElement(AutosuggestWidget_1.Autosuggest, { autosuggestField: "unit", onSuggestionSelected: this.onSuggestionSelected, renderSuggestion: this.renderSuggestion, onChange: this.onAutosuggestChange, formContext: formContext, allowNonsuggestedValue: false })));
239
+ const { formID, formContext } = this.props;
240
+ const inputElem = LINE_TRANSECT_IDS.includes(formID) ? (React.createElement(components_1.FetcherInput, { id: this.props.id, loading: this.state.loading, value: this.state.value, validationState: validationState, onChange: this.onFetcherInputChange, onBlur: this.getCode, onKeyDown: this.onKeyDown, readonly: readonly, disabled: disabled })) : (React.createElement("div", { className: "unit-shorthand" },
241
+ React.createElement(AutosuggestWidget_1.Autosuggest, { autosuggestField: "unit", query: {
242
+ formID,
243
+ includeNonMatching: true
244
+ }, onSuggestionSelected: this.onSuggestionSelected, renderSuggestion: this.renderSuggestion, onChange: this.onAutosuggestChange, formContext: formContext, allowNonsuggestedValue: false })));
241
245
  const { FormGroup, HelpBlock } = this.context.theme;
242
246
  return (React.createElement(FormGroup, { validationState: this.state.failed ? "error" : undefined },
243
247
  inputElem,
@@ -38,15 +38,6 @@ var __importStar = (this && this.__importStar) || (function () {
38
38
  return result;
39
39
  };
40
40
  })();
41
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
42
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
43
- return new (P || (P = Promise))(function (resolve, reject) {
44
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
45
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
46
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
47
- step((generator = generator.apply(thisArg, _arguments || [])).next());
48
- });
49
- };
50
41
  var __rest = (this && this.__rest) || function (s, e) {
51
42
  var t = {};
52
43
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -72,7 +63,7 @@ const components_1 = require("../components");
72
63
  const ReactContext_1 = __importDefault(require("../../ReactContext"));
73
64
  const InformalTaxonGroupChooserWidget_1 = require("./InformalTaxonGroupChooserWidget");
74
65
  function renderFlag(suggestion, prepend) {
75
- return (suggestion || {}).finnish
66
+ return (suggestion && suggestion.payload || {}).finnish
76
67
  ? React.createElement(React.Fragment, null,
77
68
  prepend || null,
78
69
  React.createElement("img", { src: "https://cdn.laji.fi/images/icons/flag_fi_small.png", width: "16" }))
@@ -82,11 +73,10 @@ class _AutosuggestWidget extends React.Component {
82
73
  render() {
83
74
  if (this.props.options) {
84
75
  switch (this.props.options.autosuggestField) {
85
- case "taxa":
86
76
  case "taxon":
87
- return React.createElement(TaxonAutosuggestWidget, Object.assign({}, this.props, { options: Object.assign(Object.assign({}, this.props.options), { autosuggestField: "taxa" }) }));
77
+ return React.createElement(TaxonAutosuggestWidget, Object.assign({}, this.props));
88
78
  case "unit":
89
- return React.createElement(UnitAutosuggestWidget, Object.assign({}, this.props, { basePath: "/shorthand/unit/trip-report" }));
79
+ return React.createElement(UnitAutosuggestWidget, Object.assign({}, this.props));
90
80
  case "friends":
91
81
  case "person":
92
82
  return React.createElement(FriendsAutosuggestWidget, Object.assign({}, this.props));
@@ -107,7 +97,6 @@ class _AutosuggestWidget extends React.Component {
107
97
  let component = undefined;
108
98
  switch (options.autosuggestField) {
109
99
  case "taxon":
110
- case "taxa":
111
100
  component = TaxonAutosuggestWidget;
112
101
  break;
113
102
  case "unit":
@@ -187,7 +176,11 @@ function TaxonAutosuggest(ComposedComponent) {
187
176
  orWriteSpeciesNameLabel || this.props.formContext.translations.orWriteSpeciesName))));
188
177
  };
189
178
  this.onTaxonImgSelected = (taxonID, taxon) => {
190
- this.autosuggestRef.selectSuggestion(Object.assign({ key: taxonID, value: taxon.vernacularName }, taxon));
179
+ this.autosuggestRef.selectSuggestion({
180
+ key: taxonID,
181
+ value: taxon.vernacularName,
182
+ payload: taxon
183
+ });
191
184
  };
192
185
  this.setAutosuggestRef = (elem) => {
193
186
  this.autosuggestRef = elem;
@@ -219,20 +212,19 @@ function TaxonAutosuggest(ComposedComponent) {
219
212
  }
220
213
  }
221
214
  getSuggestionFromValue(value) {
222
- return __awaiter(this, void 0, void 0, function* () {
223
- if (this.isValueSuggested(value)) {
224
- const { vernacularName, scientificName } = yield this.props.formContext.apiClient.get(`/taxa/${id}`);
215
+ if (this.isValueSuggested(value)) {
216
+ return this.props.formContext.apiClient.fetchCached(`/taxa/${value}`).then(({ vernacularName, scientificName }) => {
225
217
  if (vernacularName !== undefined) {
226
218
  return { value: vernacularName, key: value };
227
219
  }
228
220
  if (scientificName !== undefined) {
229
221
  return { value: scientificName, key: value };
230
222
  }
231
- }
232
- else {
233
- throw new Error("Unknown taxon");
234
- }
235
- });
223
+ });
224
+ }
225
+ else {
226
+ return Promise.reject();
227
+ }
236
228
  }
237
229
  isValueSuggested(value) {
238
230
  return !(0, utils_1.isEmptyString)(value) && !!value.match(/MX\.\d+/);
@@ -280,10 +272,10 @@ let UnitAutosuggestWidget = class UnitAutosuggestWidget extends React.Component
280
272
  this.renderSuggestion = this.renderSuggestion.bind(this);
281
273
  }
282
274
  renderSuggestion(suggestion) {
283
- const { count, maleIndividualCount, femaleIndividualCount } = suggestion.interpretedFrom;
275
+ const { count, maleIndividualCount, femaleIndividualCount } = suggestion.payload.interpretedFrom;
284
276
  const [countElem, maleElem, femaleElem] = [count, maleIndividualCount, femaleIndividualCount].map(val => val && React.createElement("span", { className: "text-muted" }, val));
285
- const taxonName = suggestion.unit.identifications[0].taxon;
286
- const name = suggestion.isNonMatching
277
+ const taxonName = suggestion.payload.unit.identifications[0].taxon;
278
+ const name = suggestion.payload.isNonMatching
287
279
  ? React.createElement("span", { className: "text-muted" },
288
280
  taxonName,
289
281
  " ",
@@ -326,11 +318,10 @@ class FriendsAutosuggestWidget extends React.Component {
326
318
  this.isValueSuggested = this.isValueSuggested.bind(this);
327
319
  }
328
320
  getSuggestionFromValue(value) {
329
- return __awaiter(this, void 0, void 0, function* () {
330
- const { showID } = (0, utils_1.getUiOptions)(this.props);
331
- const { isAdmin } = this.props.formContext.uiSchemaContext;
332
- if (this.isValueSuggested(value)) {
333
- const { fullName, group, id } = yield this.props.formContext.apiClient.get(`/person/by-id/${value}`);
321
+ const { showID } = (0, utils_1.getUiOptions)(this.props);
322
+ const { isAdmin } = this.props.formContext.uiSchemaContext;
323
+ if (this.isValueSuggested(value)) {
324
+ return this.props.formContext.apiClient.fetchCached(`/person/by-id/${value}`).then(({ fullName, group, id }) => {
334
325
  if (fullName) {
335
326
  const addGroup = str => group ? `${str} (${group})` : str;
336
327
  const addID = str => isAdmin && showID ? `${str} (${id})` : str;
@@ -339,11 +330,11 @@ class FriendsAutosuggestWidget extends React.Component {
339
330
  key: value
340
331
  };
341
332
  }
342
- }
343
- else {
344
- throw new Error("Unknown friend");
345
- }
346
- });
333
+ });
334
+ }
335
+ else {
336
+ return Promise.reject();
337
+ }
347
338
  }
348
339
  isValueSuggested(value) {
349
340
  return !(0, utils_1.isEmptyString)(value) && value.match(/MA\.\d+/);
@@ -391,21 +382,22 @@ class BasicAutosuggestWidget extends React.Component {
391
382
  this.isValueSuggested = this.isValueSuggested.bind(this);
392
383
  }
393
384
  getSuggestionFromValue(value) {
394
- return __awaiter(this, void 0, void 0, function* () {
395
- const { autosuggestField, nameField } = this.props;
396
- if (this.isValueSuggested(value)) {
397
- const result = yield this.props.formContext.apiClient.get(`/${autosuggestField}/by-id/${value}`, undefined, this.props.cache);
385
+ const { autosuggestField, nameField } = this.props;
386
+ if (this.isValueSuggested(value)) {
387
+ const apiClient = this.props.formContext.apiClient;
388
+ const fetch = (this.props.cache ? apiClient.fetchCached : apiClient.fetch).bind(apiClient);
389
+ return fetch(`/${autosuggestField}/by-id/${value}`).then(result => {
398
390
  if (result[nameField]) {
399
391
  return {
400
392
  value: result[nameField],
401
393
  key: value
402
394
  };
403
395
  }
404
- }
405
- else {
406
- throw new Error("Not autosuggested value");
407
- }
408
- });
396
+ });
397
+ }
398
+ else {
399
+ return Promise.reject();
400
+ }
409
401
  }
410
402
  isValueSuggested(value) {
411
403
  const regexp = new RegExp(this.props.validValueRegexp);
@@ -544,12 +536,12 @@ class Autosuggest extends React.Component {
544
536
  const { findExactMatch } = this.props;
545
537
  return findExactMatch
546
538
  ? findExactMatch(suggestions, inputValue)
547
- : suggestions.find(suggestion => (suggestion && suggestion.value.toLowerCase() === inputValue.trim().toLowerCase() && !suggestion.isNonMatching));
539
+ : suggestions.find(suggestion => (suggestion && suggestion.value.toLowerCase() === inputValue.trim().toLowerCase() && (!suggestion.payload || !suggestion.payload.isNonMatching)));
548
540
  };
549
541
  this.findTheOnlyOneMatch = (suggestions) => {
550
542
  if (!Array.isArray(suggestions))
551
543
  suggestions = [suggestions];
552
- const filtered = suggestions.filter(suggestion => !suggestion || !suggestion.isNonMatching);
544
+ const filtered = suggestions.filter(suggestion => !suggestion || !suggestion.payload || !suggestion.payload.isNonMatching);
553
545
  if (filtered.length === 1) {
554
546
  return filtered[0];
555
547
  }
@@ -557,7 +549,7 @@ class Autosuggest extends React.Component {
557
549
  this.findNonMatching = (suggestions) => {
558
550
  if (!Array.isArray(suggestions))
559
551
  suggestions = [suggestions];
560
- const filtered = suggestions.filter(suggestion => suggestion && suggestion.isNonMatching);
552
+ const filtered = suggestions.filter(suggestion => suggestion && suggestion.payload && suggestion.payload.isNonMatching);
561
553
  if (filtered.length === 1) {
562
554
  return filtered[0];
563
555
  }
@@ -580,15 +572,11 @@ class Autosuggest extends React.Component {
580
572
  }
581
573
  const { autosuggestField, query = {} } = this.props;
582
574
  this.setState({ isLoading: true });
583
- const request = () => __awaiter(this, void 0, void 0, function* () {
575
+ const request = () => {
584
576
  let timestamp = Date.now();
585
577
  this.promiseTimestamp = timestamp;
586
- try {
587
- let suggestionsResponse = yield this.apiClient.get(this.props.basePath || "/autocomplete" + "/" + autosuggestField, { query: Object.assign({
588
- // Hack for laji-form in Kotka, since it uses API that isn't laji-api and q was renamed to query in laji-api
589
- q: value, query: value, matchType: "exact,partial", includeHidden: false }, query) }, this.props.cache);
590
- // Hack for laji-form in Kotka, since it uses API that isn't laji-api and might have different response signature.
591
- let suggestions = Array.isArray(suggestionsResponse) ? suggestionsResponse : suggestionsResponse.results;
578
+ const fetch = (this.props.cache ? this.apiClient.fetchCached : this.apiClient.fetch).bind(this.apiClient);
579
+ fetch("/autocomplete/" + autosuggestField, Object.assign({ q: value, includePayload: true, matchType: "exact,partial", includeHidden: false }, query)).then(suggestions => {
592
580
  if (this.props.prepareSuggestion) {
593
581
  suggestions = suggestions.map(s => this.props.prepareSuggestion(s));
594
582
  }
@@ -598,13 +586,12 @@ class Autosuggest extends React.Component {
598
586
  this.mounted
599
587
  ? this.setState({ isLoading: false, suggestions }, () => this.afterBlurAndFetch(suggestions))
600
588
  : this.afterBlurAndFetch(suggestions);
601
- }
602
- catch (e) {
589
+ }).catch(() => {
603
590
  this.mounted
604
591
  ? this.setState({ isLoading: false }, this.afterBlurAndFetch)
605
592
  : this.afterBlurAndFetch();
606
- }
607
- });
593
+ });
594
+ };
608
595
  if (this.timeout) {
609
596
  clearTimeout(this.timeout);
610
597
  }
@@ -815,10 +802,10 @@ class Autosuggest extends React.Component {
815
802
  ? this.props.highlightFirstSuggestion
816
803
  : !this.props.allowNonsuggestedValue;
817
804
  const { renderExtra } = props;
818
- return React.createElement(React.Fragment, null,
805
+ return (React.createElement(React.Fragment, null,
819
806
  renderExtra && renderExtra(),
820
807
  React.createElement("div", { className: (0, utils_1.classNames)("autosuggest-wrapper", props.wrapperClassName) },
821
- React.createElement(ReactAutosuggest, { id: `${this.props.id}-autosuggest`, inputProps: inputProps, renderInputComponent: this.renderInput, suggestions: suggestions, renderSuggestion: this.renderSuggestion, onSuggestionsFetchRequested: this.onSuggestionsFetchRequested, onSuggestionsClearRequested: this.onSuggestionsClearRequested, onSuggestionSelected: this.onSuggestionSelected, onUnsuggestedSelected: this.onUnsuggestedSelected, highlightFirstSuggestion: highlightFirstSuggestion, suggestionsOpenOnFocus: !this.isSuggested(), theme: cssClasses, formContext: this.props.formContext, ref: this.setRef })));
808
+ React.createElement(ReactAutosuggest, { id: `${this.props.id}-autosuggest`, inputProps: inputProps, renderInputComponent: this.renderInput, suggestions: suggestions, renderSuggestion: this.renderSuggestion, onSuggestionsFetchRequested: this.onSuggestionsFetchRequested, onSuggestionsClearRequested: this.onSuggestionsClearRequested, onSuggestionSelected: this.onSuggestionSelected, onUnsuggestedSelected: this.onUnsuggestedSelected, highlightFirstSuggestion: highlightFirstSuggestion, suggestionsOpenOnFocus: !this.isSuggested(), theme: cssClasses, formContext: this.props.formContext, ref: this.setRef }))));
822
809
  }
823
810
  }
824
811
  exports.Autosuggest = Autosuggest;
@@ -855,22 +842,21 @@ class _TaxonWrapper extends React.Component {
855
842
  this.fetch(value);
856
843
  }
857
844
  fetch(value) {
858
- return __awaiter(this, void 0, void 0, function* () {
859
- if (!value) {
860
- this.setState({ scientificName: "", cursiveName: false });
861
- }
862
- else {
863
- this.props.formContext.apiClient.get(`/taxa/${value}`).then(({ scientificName, cursiveName, vernacularName, taxonRank, informalGroups, finnish }) => {
845
+ if (!value) {
846
+ this.setState({ scientificName: "", cursiveName: false });
847
+ }
848
+ else {
849
+ this.props.formContext.apiClient.fetchCached(`/taxa/${value}`).then(({ scientificName, cursiveName, vernacularName, taxonRank, informalTaxonGroups, finnish }) => {
850
+ if (!this.mounted)
851
+ return;
852
+ this.setState({ value, taxonRank, informalTaxonGroups, taxon: { scientificName, vernacularName, cursiveName, finnish } });
853
+ (0, InformalTaxonGroupChooserWidget_1.getInformalGroups)(this.props.formContext.apiClient).then(({ informalTaxonGroupsById }) => {
864
854
  if (!this.mounted)
865
855
  return;
866
- this.setState({ value, taxonRank, informalTaxonGroups: informalGroups, taxon: { scientificName, vernacularName, cursiveName, finnish } });
867
- (0, InformalTaxonGroupChooserWidget_1.getInformalGroups)(this.props.formContext.apiClient).then(({ informalTaxonGroupsById }) => {
868
- if (!this.mounted)
869
- return;
870
- this.setState({ informalTaxonGroupsById });
871
- });
856
+ this.setState({ informalTaxonGroupsById });
872
857
  });
873
- const parents = (yield this.props.formContext.apiClient.get(`/taxa/${value}/parents`)).results;
858
+ });
859
+ this.props.formContext.apiClient.fetchCached(`/taxa/${value}/parents`).then(parents => {
874
860
  if (!this.mounted)
875
861
  return;
876
862
  const state = { order: undefined, family: undefined };
@@ -888,12 +874,13 @@ class _TaxonWrapper extends React.Component {
888
874
  }
889
875
  }
890
876
  this.setState(Object.assign(Object.assign({}, state), { higherThanOrder: !state.order && !state.family }));
891
- const taxonRanks = yield this.props.formContext.apiClient.get("/metadata/ranges/MX.taxonRankEnum");
877
+ });
878
+ this.props.formContext.apiClient.fetchCached("/metadata/ranges/MX.taxonRankEnum").then(taxonRanks => {
892
879
  if (!this.mounted)
893
880
  return;
894
881
  this.setState({ taxonRanks: (0, utils_1.dictionarify)(taxonRanks, function getKey(rank) { return rank.id; }, function getValue(rank) { return rank.value; }) });
895
- }
896
- });
882
+ });
883
+ }
897
884
  }
898
885
  render() {
899
886
  const { id, formContext, value, children, placement, inputValue, isSuggested } = this.props;
@@ -1008,7 +995,7 @@ class TaxonImgChooser extends React.Component {
1008
995
  }
1009
996
  componentDidMount() {
1010
997
  this.mounted = true;
1011
- this.props.formContext.apiClient.get(`/taxa/${this.props.id}`, { query: { includeMedia: true } }).then(taxon => {
998
+ this.props.formContext.apiClient.fetchCached(`/taxa/${this.props.id}`, { includeMedia: true }).then(taxon => {
1012
999
  if (!this.mounted)
1013
1000
  return;
1014
1001
  if (taxon.multimedia && taxon.multimedia.length) {
@@ -1055,7 +1042,7 @@ const TaxonName = ({ scientificName, vernacularName = "", cursiveName, finnish }
1055
1042
  return (React.createElement(React.Fragment, null,
1056
1043
  `${vernacularName}${vernacularName ? " " : ""}`,
1057
1044
  cursiveName ? React.createElement("i", null, _scientificName) : _scientificName,
1058
- renderFlag({ finnish }, " ")));
1045
+ renderFlag({ payload: { finnish } }, " ")));
1059
1046
  };
1060
1047
  class ReactAutosuggest extends React.Component {
1061
1048
  constructor(props) {
@@ -161,7 +161,7 @@ function getInformalGroups(apiClient) {
161
161
  if (informalTaxonGroups) {
162
162
  return Promise.resolve({ informalTaxonGroups, informalTaxonGroupsById });
163
163
  }
164
- return apiClient.get("/informal-taxon-groups/tree").then(response => {
164
+ return apiClient.fetchCached("/informal-taxon-groups/tree").then(response => {
165
165
  // Contains the current taxon group.
166
166
  const informalTaxonGroups = mapGroupsById(response.results);
167
167
  // Contains all groups in flat object.
@@ -54,8 +54,9 @@ class InputWithDefaultValueButtonWidget extends React.Component {
54
54
  else if (apiQueryForDefaultValue) {
55
55
  const { path, query = {}, resultKey, cache = false } = apiQueryForDefaultValue;
56
56
  const apiClient = this.props.formContext.apiClient;
57
+ const fetch = (cache ? apiClient.fetchCached : apiClient.fetch).bind(apiClient);
57
58
  this.setState({ fetching: true });
58
- return apiClient.get(path, { query }, cache).then(result => {
59
+ return fetch(path, query).then(result => {
59
60
  if (result[resultKey]) {
60
61
  this.props.onChange(result[resultKey]);
61
62
  }
package/lib/validation.js CHANGED
@@ -39,7 +39,7 @@ exports.toErrorSchema = toErrorSchema;
39
39
  const lajiValidate = __importStar(require("@luomus/laji-validate"));
40
40
  function initializeValidation(apiClient) {
41
41
  lajiValidate.extend(lajiValidate.validators.remote, {
42
- fetch: (...params) => apiClient.apiClient.fetch(...params)
42
+ fetch: (...params) => apiClient.fetchRaw(...params)
43
43
  });
44
44
  }
45
45
  exports.default = ({ errors: error, warnings: warning }, data) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luomus/laji-form",
3
- "version": "15.1.68",
3
+ "version": "15.1.69",
4
4
  "description": "React module capable of building dynamic forms from Laji form json schemas",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -28,8 +28,7 @@
28
28
  "test:docker": "npm run test:docker:build && npm run test:docker:run --",
29
29
  "test:lightweight": "npx playwright test --project chromium",
30
30
  "test:docker:build": "docker build -t laji-form-test -f test.Dockerfile .",
31
- "test:docker:run": "docker run laji-form-test",
32
- "generate:api-client": "openapi-typescript https://apitest.laji.fi/explorer-json -o ./generated/api.d.ts --properties-required-by-default"
31
+ "test:docker:run": "docker run laji-form-test"
33
32
  },
34
33
  "keywords": [
35
34
  "react-jsonschema-form",
@@ -72,7 +71,7 @@
72
71
  "@playwright/test": "^1.40.1",
73
72
  "@stylistic/eslint-plugin": "^5.4.0",
74
73
  "@types/jasmine": "^3.7.7",
75
- "@types/node": "^24.5.2",
74
+ "@types/node": "^20.17.0",
76
75
  "@typescript-eslint/eslint-plugin": "^8.44.1",
77
76
  "@typescript-eslint/parser": "^8.44.1",
78
77
  "copy-webpack-plugin": "^9.0.1",
@@ -83,7 +82,6 @@
83
82
  "eslint-plugin-react-hooks": "^5.2.0",
84
83
  "mini-css-extract-plugin": "^2.1.0",
85
84
  "notus": "^0.3.2",
86
- "openapi-typescript": "^7.9.1",
87
85
  "querystring": "^0.2.1",
88
86
  "rimraf": "^2.5.4",
89
87
  "style-loader": "^3.0.0",