@luomus/laji-form 15.1.65 → 15.1.67

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 (33) hide show
  1. package/dist/laji-form.js +1 -1
  2. package/lib/ApiClient.d.ts +64 -21
  3. package/lib/ApiClient.js +172 -68
  4. package/lib/components/LajiForm.js +1 -1
  5. package/lib/components/components/DeleteButton.d.ts +1 -0
  6. package/lib/components/components/DeleteButton.js +6 -1
  7. package/lib/components/fields/AnnotationField.js +26 -22
  8. package/lib/components/fields/AudioArrayField.js +18 -5
  9. package/lib/components/fields/AutosuggestField.d.ts +2 -2
  10. package/lib/components/fields/AutosuggestField.js +4 -4
  11. package/lib/components/fields/EnumRangeArrayField.js +1 -1
  12. package/lib/components/fields/GeocoderField.js +2 -9
  13. package/lib/components/fields/ImageArrayField.d.ts +3 -2
  14. package/lib/components/fields/ImageArrayField.js +85 -113
  15. package/lib/components/fields/MapArrayField.js +13 -5
  16. package/lib/components/fields/MapField.d.ts +1 -1
  17. package/lib/components/fields/MapField.js +13 -5
  18. package/lib/components/fields/NamedPlaceChooserField/NamedPlaceChooser.d.ts +2 -1
  19. package/lib/components/fields/NamedPlaceChooserField/NamedPlaceChooserField.d.ts +9 -4
  20. package/lib/components/fields/NamedPlaceChooserField/NamedPlaceChooserField.js +52 -51
  21. package/lib/components/fields/NamedPlaceChooserField/Popup.d.ts +2 -1
  22. package/lib/components/fields/NamedPlaceSaverField.js +22 -18
  23. package/lib/components/fields/ScopeField.js +1 -1
  24. package/lib/components/fields/SingleActiveArrayField.js +2 -2
  25. package/lib/components/fields/SortArrayField.js +1 -1
  26. package/lib/components/fields/UnitCountShorthandField.js +1 -1
  27. package/lib/components/fields/UnitListShorthandArrayField.js +2 -2
  28. package/lib/components/fields/UnitShorthandField.js +4 -4
  29. package/lib/components/widgets/AutosuggestWidget.js +79 -66
  30. package/lib/components/widgets/InformalTaxonGroupChooserWidget.js +1 -1
  31. package/lib/components/widgets/InputWithDefaultValueButtonWidget.js +1 -2
  32. package/lib/validation.js +1 -1
  33. package/package.json +5 -3
@@ -38,6 +38,15 @@ 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
+ };
41
50
  var __rest = (this && this.__rest) || function (s, e) {
42
51
  var t = {};
43
52
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -182,7 +191,7 @@ class PlaceSaverDialog extends React.Component {
182
191
  }
183
192
  componentDidMount() {
184
193
  this.mounted = true;
185
- this.apiClient.fetchCached("/named-places", { includePublic: false, pageSize: 1000 }).then(response => {
194
+ this.apiClient.get("/named-places", { query: { includePublic: false, pageSize: 100000 } }).then(response => {
186
195
  if (!this.mounted)
187
196
  return;
188
197
  const state = {
@@ -213,23 +222,18 @@ class PlaceSaverDialog extends React.Component {
213
222
  });
214
223
  }
215
224
  onSave(place) {
216
- place = Object.assign(Object.assign({}, place), { geometry: place.prepopulatedDocument.gatherings[0].geometry });
217
- this.props.formContext.services.blocker.push();
218
- this.apiClient.fetchRaw(`/named-places${place.id ? `/${place.id}` : ""}`, undefined, {
219
- method: place.id ? "PUT" : "POST",
220
- headers: {
221
- "accept": "application/json",
222
- "content-type": "application/json"
223
- },
224
- body: JSON.stringify(place)
225
- }).then(response => {
226
- this.props.formContext.services.blocker.pop();
227
- this.apiClient.invalidateCachePath("/named-places");
228
- return response.json();
229
- }).then(this.props.onSave)
230
- .catch(() => {
231
- this.props.formContext.services.blocker.pop();
232
- this.setState({ failed: SAVE });
225
+ return __awaiter(this, void 0, void 0, function* () {
226
+ place = Object.assign(Object.assign({}, place), { geometry: place.prepopulatedDocument.gatherings[0].geometry });
227
+ this.props.formContext.services.blocker.push();
228
+ try {
229
+ const savedPlace = yield this.apiClient[place.id ? "put" : "post"](`/named-places${place.id ? "/{id}" : ""}`, place.id ? { path: { id: place.id } } : undefined, place);
230
+ this.props.formContext.services.blocker.pop();
231
+ yield this.props.onSave(savedPlace);
232
+ }
233
+ catch (e) {
234
+ this.props.formContext.services.blocker.pop();
235
+ this.setState({ failed: SAVE });
236
+ }
233
237
  });
234
238
  }
235
239
  render() {
@@ -50,7 +50,7 @@ const utils_2 = require("@rjsf/utils");
50
50
  const scopeFieldSettings = {
51
51
  taxonGroups: {
52
52
  translate: (props, taxonGroup) => {
53
- return props.formContext.apiClient.fetchCached("/informal-taxon-groups/" + taxonGroup).then((response) => {
53
+ return props.formContext.apiClient.get("/informal-taxon-groups/" + taxonGroup).then((response) => {
54
54
  return response.name;
55
55
  }).catch(() => {
56
56
  return "";
@@ -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.fetchCached(`/named-places/${namedPlaceID}`, undefined, { failSilently: true }).then(response => {
914
+ props.that.props.formContext.apiClient.get("/named-places/{id}", { path: { id: namedPlaceID } }).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
- });
920
+ }).catch(() => { });
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.fetchCached("/taxa", Object.assign(Object.assign({}, this.options.query), { pageSize: 10000, selectedFields: "id" })))
72
+ this.idToIdx = (yield this.formContext.apiClient.get("/taxa", { query: 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.fetchCached("/autocomplete/pairCount", { q: value, taxonID: taxonId }).then(suggestion => {
85
+ apiClient.get("/shorthand/unit/water-bird-pair-count", { query: { query: 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.fetch("/autocomplete/unit", { q: value, list: true, includePayload: true }).then(({ payload: { units, nonMatchingCount } }) => {
73
- units = units.map(unit => {
72
+ apiClient.get("/shorthand/unit/list", { query: { query: value } }).then(({ results, nonMatchingCount }) => {
73
+ const units = results.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);
@@ -185,14 +185,14 @@ let CodeReader = class CodeReader extends React.Component {
185
185
  this.onAutosuggestChange = (formData) => {
186
186
  this.props.onChange(formData);
187
187
  };
188
- this.onSuggestionSelected = ({ payload: { unit } }) => {
188
+ this.onSuggestionSelected = ({ unit }) => {
189
189
  const { formContext } = this.props;
190
190
  unit = (0, utils_1.bringRemoteFormData)(unit, formContext);
191
191
  this.props.onChange(unit);
192
192
  };
193
193
  this.renderSuggestion = (suggestion) => {
194
194
  const { translations } = this.props;
195
- return suggestion.payload.isNonMatching
195
+ return suggestion.isNonMatching
196
196
  ? React.createElement("span", { className: "text-muted" },
197
197
  suggestion.value,
198
198
  " ",
@@ -212,8 +212,8 @@ let CodeReader = class CodeReader extends React.Component {
212
212
  }
213
213
  else if (value.length >= 3) {
214
214
  this.mounted && this.setState({ loading: true });
215
- this.apiClient.fetchCached("/autocomplete/unit", { q: value, formID: this.props.formID, includePayload: true }).then(response => {
216
- this.props.onChange(response.payload.unit);
215
+ this.apiClient.get("/shorthand/unit/line-transect", { query: { query: value } }).then(response => {
216
+ this.props.onChange(response.unit);
217
217
  }).catch(() => {
218
218
  this.mounted && this.setState({ failed: true, loading: false });
219
219
  });
@@ -38,6 +38,15 @@ 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
+ };
41
50
  var __rest = (this && this.__rest) || function (s, e) {
42
51
  var t = {};
43
52
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -63,7 +72,7 @@ const components_1 = require("../components");
63
72
  const ReactContext_1 = __importDefault(require("../../ReactContext"));
64
73
  const InformalTaxonGroupChooserWidget_1 = require("./InformalTaxonGroupChooserWidget");
65
74
  function renderFlag(suggestion, prepend) {
66
- return (suggestion && suggestion.payload || {}).finnish
75
+ return (suggestion || {}).finnish
67
76
  ? React.createElement(React.Fragment, null,
68
77
  prepend || null,
69
78
  React.createElement("img", { src: "https://cdn.laji.fi/images/icons/flag_fi_small.png", width: "16" }))
@@ -73,10 +82,11 @@ class _AutosuggestWidget extends React.Component {
73
82
  render() {
74
83
  if (this.props.options) {
75
84
  switch (this.props.options.autosuggestField) {
85
+ case "taxa":
76
86
  case "taxon":
77
- return React.createElement(TaxonAutosuggestWidget, Object.assign({}, this.props));
87
+ return React.createElement(TaxonAutosuggestWidget, Object.assign({}, this.props, { options: Object.assign(Object.assign({}, this.props.options), { autosuggestField: "taxa" }) }));
78
88
  case "unit":
79
- return React.createElement(UnitAutosuggestWidget, Object.assign({}, this.props));
89
+ return React.createElement(UnitAutosuggestWidget, Object.assign({}, this.props, { basePath: "/shorthand/unit/trip-report" }));
80
90
  case "friends":
81
91
  case "person":
82
92
  return React.createElement(FriendsAutosuggestWidget, Object.assign({}, this.props));
@@ -97,6 +107,7 @@ class _AutosuggestWidget extends React.Component {
97
107
  let component = undefined;
98
108
  switch (options.autosuggestField) {
99
109
  case "taxon":
110
+ case "taxa":
100
111
  component = TaxonAutosuggestWidget;
101
112
  break;
102
113
  case "unit":
@@ -176,11 +187,7 @@ function TaxonAutosuggest(ComposedComponent) {
176
187
  orWriteSpeciesNameLabel || this.props.formContext.translations.orWriteSpeciesName))));
177
188
  };
178
189
  this.onTaxonImgSelected = (taxonID, taxon) => {
179
- this.autosuggestRef.selectSuggestion({
180
- key: taxonID,
181
- value: taxon.vernacularName,
182
- payload: taxon
183
- });
190
+ this.autosuggestRef.selectSuggestion(Object.assign({ key: taxonID, value: taxon.vernacularName }, taxon));
184
191
  };
185
192
  this.setAutosuggestRef = (elem) => {
186
193
  this.autosuggestRef = elem;
@@ -212,19 +219,20 @@ function TaxonAutosuggest(ComposedComponent) {
212
219
  }
213
220
  }
214
221
  getSuggestionFromValue(value) {
215
- if (this.isValueSuggested(value)) {
216
- return this.props.formContext.apiClient.fetchCached(`/taxa/${value}`).then(({ vernacularName, scientificName }) => {
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}`);
217
225
  if (vernacularName !== undefined) {
218
226
  return { value: vernacularName, key: value };
219
227
  }
220
228
  if (scientificName !== undefined) {
221
229
  return { value: scientificName, key: value };
222
230
  }
223
- });
224
- }
225
- else {
226
- return Promise.reject();
227
- }
231
+ }
232
+ else {
233
+ throw new Error("Unknown taxon");
234
+ }
235
+ });
228
236
  }
229
237
  isValueSuggested(value) {
230
238
  return !(0, utils_1.isEmptyString)(value) && !!value.match(/MX\.\d+/);
@@ -272,10 +280,10 @@ let UnitAutosuggestWidget = class UnitAutosuggestWidget extends React.Component
272
280
  this.renderSuggestion = this.renderSuggestion.bind(this);
273
281
  }
274
282
  renderSuggestion(suggestion) {
275
- const { count, maleIndividualCount, femaleIndividualCount } = suggestion.payload.interpretedFrom;
283
+ const { count, maleIndividualCount, femaleIndividualCount } = suggestion.interpretedFrom;
276
284
  const [countElem, maleElem, femaleElem] = [count, maleIndividualCount, femaleIndividualCount].map(val => val && React.createElement("span", { className: "text-muted" }, val));
277
- const taxonName = suggestion.payload.unit.identifications[0].taxon;
278
- const name = suggestion.payload.isNonMatching
285
+ const taxonName = suggestion.unit.identifications[0].taxon;
286
+ const name = suggestion.isNonMatching
279
287
  ? React.createElement("span", { className: "text-muted" },
280
288
  taxonName,
281
289
  " ",
@@ -318,10 +326,11 @@ class FriendsAutosuggestWidget extends React.Component {
318
326
  this.isValueSuggested = this.isValueSuggested.bind(this);
319
327
  }
320
328
  getSuggestionFromValue(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 }) => {
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}`);
325
334
  if (fullName) {
326
335
  const addGroup = str => group ? `${str} (${group})` : str;
327
336
  const addID = str => isAdmin && showID ? `${str} (${id})` : str;
@@ -330,11 +339,11 @@ class FriendsAutosuggestWidget extends React.Component {
330
339
  key: value
331
340
  };
332
341
  }
333
- });
334
- }
335
- else {
336
- return Promise.reject();
337
- }
342
+ }
343
+ else {
344
+ throw new Error("Unknown friend");
345
+ }
346
+ });
338
347
  }
339
348
  isValueSuggested(value) {
340
349
  return !(0, utils_1.isEmptyString)(value) && value.match(/MA\.\d+/);
@@ -382,22 +391,21 @@ class BasicAutosuggestWidget extends React.Component {
382
391
  this.isValueSuggested = this.isValueSuggested.bind(this);
383
392
  }
384
393
  getSuggestionFromValue(value) {
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 => {
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);
390
398
  if (result[nameField]) {
391
399
  return {
392
400
  value: result[nameField],
393
401
  key: value
394
402
  };
395
403
  }
396
- });
397
- }
398
- else {
399
- return Promise.reject();
400
- }
404
+ }
405
+ else {
406
+ throw new Error("Not autosuggested value");
407
+ }
408
+ });
401
409
  }
402
410
  isValueSuggested(value) {
403
411
  const regexp = new RegExp(this.props.validValueRegexp);
@@ -536,12 +544,12 @@ class Autosuggest extends React.Component {
536
544
  const { findExactMatch } = this.props;
537
545
  return findExactMatch
538
546
  ? findExactMatch(suggestions, inputValue)
539
- : suggestions.find(suggestion => (suggestion && suggestion.value.toLowerCase() === inputValue.trim().toLowerCase() && (!suggestion.payload || !suggestion.payload.isNonMatching)));
547
+ : suggestions.find(suggestion => (suggestion && suggestion.value.toLowerCase() === inputValue.trim().toLowerCase() && !suggestion.isNonMatching));
540
548
  };
541
549
  this.findTheOnlyOneMatch = (suggestions) => {
542
550
  if (!Array.isArray(suggestions))
543
551
  suggestions = [suggestions];
544
- const filtered = suggestions.filter(suggestion => !suggestion || !suggestion.payload || !suggestion.payload.isNonMatching);
552
+ const filtered = suggestions.filter(suggestion => !suggestion || !suggestion.isNonMatching);
545
553
  if (filtered.length === 1) {
546
554
  return filtered[0];
547
555
  }
@@ -549,7 +557,7 @@ class Autosuggest extends React.Component {
549
557
  this.findNonMatching = (suggestions) => {
550
558
  if (!Array.isArray(suggestions))
551
559
  suggestions = [suggestions];
552
- const filtered = suggestions.filter(suggestion => suggestion && suggestion.payload && suggestion.payload.isNonMatching);
560
+ const filtered = suggestions.filter(suggestion => suggestion && suggestion.isNonMatching);
553
561
  if (filtered.length === 1) {
554
562
  return filtered[0];
555
563
  }
@@ -572,11 +580,15 @@ class Autosuggest extends React.Component {
572
580
  }
573
581
  const { autosuggestField, query = {} } = this.props;
574
582
  this.setState({ isLoading: true });
575
- const request = () => {
583
+ const request = () => __awaiter(this, void 0, void 0, function* () {
576
584
  let timestamp = Date.now();
577
585
  this.promiseTimestamp = timestamp;
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 => {
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;
580
592
  if (this.props.prepareSuggestion) {
581
593
  suggestions = suggestions.map(s => this.props.prepareSuggestion(s));
582
594
  }
@@ -586,12 +598,13 @@ class Autosuggest extends React.Component {
586
598
  this.mounted
587
599
  ? this.setState({ isLoading: false, suggestions }, () => this.afterBlurAndFetch(suggestions))
588
600
  : this.afterBlurAndFetch(suggestions);
589
- }).catch(() => {
601
+ }
602
+ catch (e) {
590
603
  this.mounted
591
604
  ? this.setState({ isLoading: false }, this.afterBlurAndFetch)
592
605
  : this.afterBlurAndFetch();
593
- });
594
- };
606
+ }
607
+ });
595
608
  if (this.timeout) {
596
609
  clearTimeout(this.timeout);
597
610
  }
@@ -802,10 +815,10 @@ class Autosuggest extends React.Component {
802
815
  ? this.props.highlightFirstSuggestion
803
816
  : !this.props.allowNonsuggestedValue;
804
817
  const { renderExtra } = props;
805
- return (React.createElement(React.Fragment, null,
818
+ return React.createElement(React.Fragment, null,
806
819
  renderExtra && renderExtra(),
807
820
  React.createElement("div", { className: (0, utils_1.classNames)("autosuggest-wrapper", props.wrapperClassName) },
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 }))));
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 })));
809
822
  }
810
823
  }
811
824
  exports.Autosuggest = Autosuggest;
@@ -842,21 +855,22 @@ class _TaxonWrapper extends React.Component {
842
855
  this.fetch(value);
843
856
  }
844
857
  fetch(value) {
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 }) => {
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 }) => {
854
864
  if (!this.mounted)
855
865
  return;
856
- this.setState({ informalTaxonGroupsById });
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
+ });
857
872
  });
858
- });
859
- this.props.formContext.apiClient.fetchCached(`/taxa/${value}/parents`).then(parents => {
873
+ const parents = (yield this.props.formContext.apiClient.get(`/taxa/${value}/parents`)).results;
860
874
  if (!this.mounted)
861
875
  return;
862
876
  const state = { order: undefined, family: undefined };
@@ -874,13 +888,12 @@ class _TaxonWrapper extends React.Component {
874
888
  }
875
889
  }
876
890
  this.setState(Object.assign(Object.assign({}, state), { higherThanOrder: !state.order && !state.family }));
877
- });
878
- this.props.formContext.apiClient.fetchCached("/metadata/ranges/MX.taxonRankEnum").then(taxonRanks => {
891
+ const taxonRanks = yield this.props.formContext.apiClient.get("/metadata/ranges/MX.taxonRankEnum");
879
892
  if (!this.mounted)
880
893
  return;
881
894
  this.setState({ taxonRanks: (0, utils_1.dictionarify)(taxonRanks, function getKey(rank) { return rank.id; }, function getValue(rank) { return rank.value; }) });
882
- });
883
- }
895
+ }
896
+ });
884
897
  }
885
898
  render() {
886
899
  const { id, formContext, value, children, placement, inputValue, isSuggested } = this.props;
@@ -995,7 +1008,7 @@ class TaxonImgChooser extends React.Component {
995
1008
  }
996
1009
  componentDidMount() {
997
1010
  this.mounted = true;
998
- this.props.formContext.apiClient.fetchCached(`/taxa/${this.props.id}`, { includeMedia: true }).then(taxon => {
1011
+ this.props.formContext.apiClient.get(`/taxa/${this.props.id}`, { query: { includeMedia: true } }).then(taxon => {
999
1012
  if (!this.mounted)
1000
1013
  return;
1001
1014
  if (taxon.multimedia && taxon.multimedia.length) {
@@ -1042,7 +1055,7 @@ const TaxonName = ({ scientificName, vernacularName = "", cursiveName, finnish }
1042
1055
  return (React.createElement(React.Fragment, null,
1043
1056
  `${vernacularName}${vernacularName ? " " : ""}`,
1044
1057
  cursiveName ? React.createElement("i", null, _scientificName) : _scientificName,
1045
- renderFlag({ payload: { finnish } }, " ")));
1058
+ renderFlag({ finnish }, " ")));
1046
1059
  };
1047
1060
  class ReactAutosuggest extends React.Component {
1048
1061
  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.fetchCached("/informal-taxon-groups/tree").then(response => {
164
+ return apiClient.get("/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,9 +54,8 @@ 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);
58
57
  this.setState({ fetching: true });
59
- return fetch(path, query).then(result => {
58
+ return apiClient.get(path, { query }, cache).then(result => {
60
59
  if (result[resultKey]) {
61
60
  this.props.onChange(result[resultKey]);
62
61
  }
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.fetchRaw(...params)
42
+ fetch: (...params) => apiClient.apiClient.fetch(...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.65",
3
+ "version": "15.1.67",
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,7 +28,8 @@
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"
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"
32
33
  },
33
34
  "keywords": [
34
35
  "react-jsonschema-form",
@@ -71,7 +72,7 @@
71
72
  "@playwright/test": "^1.40.1",
72
73
  "@stylistic/eslint-plugin": "^5.4.0",
73
74
  "@types/jasmine": "^3.7.7",
74
- "@types/node": "^20.17.0",
75
+ "@types/node": "^24.5.2",
75
76
  "@typescript-eslint/eslint-plugin": "^8.44.1",
76
77
  "@typescript-eslint/parser": "^8.44.1",
77
78
  "copy-webpack-plugin": "^9.0.1",
@@ -82,6 +83,7 @@
82
83
  "eslint-plugin-react-hooks": "^5.2.0",
83
84
  "mini-css-extract-plugin": "^2.1.0",
84
85
  "notus": "^0.3.2",
86
+ "openapi-typescript": "^7.9.1",
85
87
  "querystring": "^0.2.1",
86
88
  "rimraf": "^2.5.4",
87
89
  "style-loader": "^3.0.0",