@luomus/laji-form 15.1.89 → 15.1.92

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.
@@ -146,6 +146,7 @@ const fields = importLocalComponents("fields", [
146
146
  "MultiActiveArrayField",
147
147
  "PrefixArrayField",
148
148
  "FillDateRangeField",
149
+ "TaxonSetPopulatorField",
149
150
  "ScientificNameTaxonAutosuggestField",
150
151
  { "InputTransformerField": "ConditionalOnChangeField" }, // Alias for backward compatibility.
151
152
  { "ConditionalField": "ConditionalUiSchemaField" }, // Alias for backward compatibility.
@@ -60,7 +60,7 @@ function EnumRangeArrayField(props) {
60
60
  propsOnChange(value);
61
61
  }, [propsOnChange]);
62
62
  const getEnumOptionsAsync = (0, react_1.useCallback)(() => __awaiter(this, void 0, void 0, function* () {
63
- const enums = yield props.formContext.apiClient.get(`/metadata/ranges/${range}`);
63
+ const enums = (yield props.formContext.apiClient.get("/metadata/alts/{alt}", { path: { alt: range } })).results;
64
64
  return enums.map(({ value }) => ({ value, label: value }));
65
65
  }), [props.formContext.apiClient, range]);
66
66
  const { Label } = props.formContext;
@@ -189,7 +189,7 @@ function MediaArrayField(ComposedComponent) {
189
189
  const metadataForm = this.state.metadataForm || {};
190
190
  if (typeof metadataModalOpen === "number" && !this.state.metadataForm) {
191
191
  const { metadataFormId = this.METADATA_FORM_ID } = (0, utils_1.getUiOptions)(this.props.uiSchema);
192
- this.apiClient.get("/forms/{id}", { path: { id: metadataFormId }, query: { lang, format: "schema" } })
192
+ this.apiClient.get("/forms/{id}", { path: { id: metadataFormId }, query: { format: "schema" } })
193
193
  .then(metadataForm => {
194
194
  if (this.mounted) {
195
195
  this.setState({ metadataForm });
@@ -22,6 +22,12 @@ export default class MultiAnyToBooleanField extends React.Component<any, any, an
22
22
  getInitialState(props: any): {
23
23
  groupsFormData: any[];
24
24
  };
25
+ getStateFromProps(props: any): {
26
+ groupsFormData: any[];
27
+ };
28
+ initializeGroups: (props: any) => {
29
+ groupsFormData: any[];
30
+ };
25
31
  onChange: (index: any) => (value: any) => void;
26
32
  render(): JSX.Element;
27
33
  }
@@ -62,6 +62,31 @@ const utils_2 = require("@rjsf/utils");
62
62
  let MultiAnyToBooleanField = class MultiAnyToBooleanField extends React.Component {
63
63
  constructor(props) {
64
64
  super(props);
65
+ this.initializeGroups = (props) => {
66
+ let { groups } = (0, utils_1.getUiOptions)(props.uiSchema) || [];
67
+ const { formData } = props;
68
+ const trueValues = groups.map(group => group.trueValue);
69
+ const falseValues = groups.map(group => group.falseValue);
70
+ const groupsFormData = [];
71
+ if (formData) {
72
+ formData.forEach(value => {
73
+ if (value === undefined) {
74
+ return;
75
+ }
76
+ const trueIndex = trueValues.findIndex(trueValue => props.formContext.utils.formDataEquals(value, trueValue, props.idSchema.$id));
77
+ if (trueIndex !== -1) {
78
+ groupsFormData[trueIndex] = value;
79
+ }
80
+ else {
81
+ const falseIndex = falseValues.findIndex(falseValue => props.formContext.utils.formDataEquals(value, falseValue, props.idSchema.$id));
82
+ if (falseIndex !== -1) {
83
+ groupsFormData[falseIndex] = value;
84
+ }
85
+ }
86
+ });
87
+ }
88
+ return { groupsFormData: groupsFormData };
89
+ };
65
90
  this.onChange = (index) => (value) => {
66
91
  const groupsFormData = this.state.groupsFormData;
67
92
  groupsFormData[index] = value;
@@ -77,29 +102,10 @@ let MultiAnyToBooleanField = class MultiAnyToBooleanField extends React.Componen
77
102
  this.state = this.getInitialState(props);
78
103
  }
79
104
  getInitialState(props) {
80
- let { groups } = (0, utils_1.getUiOptions)(props.uiSchema) || [];
81
- const { formData } = props;
82
- const trueValues = groups.map(group => group.trueValue);
83
- const falseValues = groups.map(group => group.falseValue);
84
- const groupsFormData = [];
85
- if (formData) {
86
- formData.forEach(value => {
87
- if (value === undefined) {
88
- return;
89
- }
90
- const trueIndex = trueValues.findIndex(trueValue => props.formContext.utils.formDataEquals(value, trueValue, props.idSchema.$id));
91
- if (trueIndex !== -1) {
92
- groupsFormData[trueIndex] = value;
93
- }
94
- else {
95
- const falseIndex = falseValues.findIndex(falseValue => props.formContext.utils.formDataEquals(value, falseValue, props.idSchema.$id));
96
- if (falseIndex !== -1) {
97
- groupsFormData[falseIndex] = value;
98
- }
99
- }
100
- });
101
- }
102
- return { groupsFormData: groupsFormData };
105
+ return this.initializeGroups(props);
106
+ }
107
+ getStateFromProps(props) {
108
+ return this.initializeGroups(props);
103
109
  }
104
110
  render() {
105
111
  const TitleFieldTemplate = (0, utils_2.getTemplate)("TitleFieldTemplate", this.props.registry, (0, utils_1.getUiOptions)(this.props.uiSchema));
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import { ByLang, FormContext } from "../../LajiForm";
3
3
  import memoize from "memoizee";
4
4
  import type { components } from "generated/api.d";
5
- type NamedPlace = components["schemas"]["namedPlace"];
5
+ type NamedPlace = components["schemas"]["store-namedPlace"];
6
6
  type Props = {
7
7
  places: NamedPlace[];
8
8
  failed?: boolean;
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { FieldProps, JSONSchemaArray, JSONSchemaObject } from "../../../types";
3
3
  import type { components } from "generated/api.d";
4
- type NamedPlace = components["schemas"]["namedPlace"];
4
+ type NamedPlace = components["schemas"]["store-namedPlace"];
5
5
  type Props = FieldProps<NamedPlace, JSONSchemaObject | JSONSchemaArray<JSONSchemaObject>>;
6
6
  type State = {
7
7
  show?: boolean;
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { FormContext } from "src/components/LajiForm";
3
3
  import type { components } from "generated/api.d";
4
- type NamedPlace = components["schemas"]["namedPlace"];
4
+ type NamedPlace = components["schemas"]["store-namedPlace"];
5
5
  type Props = {
6
6
  onPlaceSelected: (place: NamedPlace) => void;
7
7
  onPlaceDeleted: (place: NamedPlace) => void;
@@ -0,0 +1,50 @@
1
+ import * as React from "react";
2
+ import * as PropTypes from "prop-types";
3
+ import { FieldProps } from "../../types";
4
+ /**
5
+ * Watches a specified field which contains taxon set IDs.
6
+ *
7
+ * When taxon set IDs are added, it fetches the taxa in those sets from the API and adds them to the units in formData.
8
+ *
9
+ * When taxon set IDs are removed, it removes any taxa belonging to those sets from the units in formData.
10
+ *
11
+ * uiSchema = {
12
+ * "ui:field": "TaxonSetPopulatorField",
13
+ * "ui:options": {
14
+ * "props": {
15
+ * "from": "taxonCensus", // Source object containing taxon set IDs
16
+ * "fromArrayKey": "censusTaxonSetID", // Field within source object containing the taxon set IDs
17
+ * "joinArray": true, // Join array of IDs into comma-separated string
18
+ * }
19
+ * }
20
+ * }
21
+ */
22
+ export default class TaxonSetPopulatorField extends React.Component<FieldProps> {
23
+ static propTypes: {
24
+ uiSchema: PropTypes.Validator<NonNullable<PropTypes.InferProps<{
25
+ "ui:options": PropTypes.Requireable<PropTypes.InferProps<{
26
+ props: PropTypes.Requireable<NonNullable<PropTypes.InferProps<{
27
+ from: PropTypes.Validator<string>;
28
+ fromArrayKey: PropTypes.Requireable<string>;
29
+ joinArray: PropTypes.Requireable<boolean>;
30
+ }> | (PropTypes.InferProps<{
31
+ from: PropTypes.Validator<string>;
32
+ fromArrayKey: PropTypes.Requireable<string>;
33
+ joinArray: PropTypes.Requireable<boolean>;
34
+ }> | null | undefined)[] | null | undefined>>;
35
+ }>>;
36
+ uiSchema: PropTypes.Requireable<object>;
37
+ }>>>;
38
+ schema: PropTypes.Validator<NonNullable<PropTypes.InferProps<{
39
+ type: PropTypes.Requireable<string>;
40
+ }>>>;
41
+ formData: PropTypes.Validator<object>;
42
+ };
43
+ static getName(): string;
44
+ taxonSets: any[];
45
+ getStateFromProps(): {
46
+ onChange: (formData: any) => Promise<void>;
47
+ };
48
+ onChange: (formData: any) => Promise<void>;
49
+ private fetchTaxaFromSet;
50
+ }
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
51
+ return (mod && mod.__esModule) ? mod : { "default": mod };
52
+ };
53
+ Object.defineProperty(exports, "__esModule", { value: true });
54
+ const React = __importStar(require("react"));
55
+ const PropTypes = __importStar(require("prop-types"));
56
+ const VirtualSchemaField_1 = __importDefault(require("../VirtualSchemaField"));
57
+ const propsPropType = PropTypes.shape({
58
+ from: PropTypes.string.isRequired,
59
+ fromArrayKey: PropTypes.string,
60
+ joinArray: PropTypes.bool,
61
+ });
62
+ /**
63
+ * Watches a specified field which contains taxon set IDs.
64
+ *
65
+ * When taxon set IDs are added, it fetches the taxa in those sets from the API and adds them to the units in formData.
66
+ *
67
+ * When taxon set IDs are removed, it removes any taxa belonging to those sets from the units in formData.
68
+ *
69
+ * uiSchema = {
70
+ * "ui:field": "TaxonSetPopulatorField",
71
+ * "ui:options": {
72
+ * "props": {
73
+ * "from": "taxonCensus", // Source object containing taxon set IDs
74
+ * "fromArrayKey": "censusTaxonSetID", // Field within source object containing the taxon set IDs
75
+ * "joinArray": true, // Join array of IDs into comma-separated string
76
+ * }
77
+ * }
78
+ * }
79
+ */
80
+ let TaxonSetPopulatorField = class TaxonSetPopulatorField extends React.Component {
81
+ constructor() {
82
+ super(...arguments);
83
+ this.taxonSets = [];
84
+ this.onChange = (formData) => __awaiter(this, void 0, void 0, function* () {
85
+ var _a, _b, _c;
86
+ const previousTaxonSets = this.taxonSets;
87
+ const currentTaxonSets = ((_a = formData === null || formData === void 0 ? void 0 : formData.taxonCensus) === null || _a === void 0 ? void 0 : _a.map((item) => item.censusTaxonSetID)) || [];
88
+ const deletedTaxonSets = previousTaxonSets.filter((item) => !currentTaxonSets.includes(item));
89
+ const addedTaxonSets = currentTaxonSets.filter((item) => !previousTaxonSets.includes(item));
90
+ this.taxonSets = ((_b = formData === null || formData === void 0 ? void 0 : formData.taxonCensus) === null || _b === void 0 ? void 0 : _b.map((item) => item.censusTaxonSetID)) || [];
91
+ if (deletedTaxonSets.length > 0) {
92
+ deletedTaxonSets.map((deletedTaxonSetId) => {
93
+ var _a;
94
+ const currentUnits = Array.isArray((_a = this.props.formData) === null || _a === void 0 ? void 0 : _a.units) ? this.props.formData.units : [];
95
+ let observationsExist = false;
96
+ const deletedTaxonSetUnits = currentUnits.filter((unit) => {
97
+ return unit.taxonSets && unit.taxonSets.includes(deletedTaxonSetId);
98
+ });
99
+ deletedTaxonSetUnits.map((unit) => {
100
+ var _a, _b, _c, _d;
101
+ if (unit.maleIndividualCount ||
102
+ unit.femaleIndividualCount ||
103
+ unit.nestCount ||
104
+ ((_a = unit.unitFact) === null || _a === void 0 ? void 0 : _a.destroyedNestCount) ||
105
+ ((_b = unit.unitFact) === null || _b === void 0 ? void 0 : _b.broodCount) ||
106
+ ((_c = unit.unitFact) === null || _c === void 0 ? void 0 : _c.femalesWithBroodsCount) ||
107
+ ((_d = unit.unitFact) === null || _d === void 0 ? void 0 : _d.juvenileCount)) {
108
+ window.alert(`Warning: Can't delete taxon set "${deletedTaxonSetId}" because it has observations.`);
109
+ observationsExist = true;
110
+ const updatedFormData = Object.assign(Object.assign({}, formData), { taxonCensus: [
111
+ ...formData.taxonCensus,
112
+ {
113
+ censusTaxonSetID: deletedTaxonSetId,
114
+ taxonCensusType: "MY.taxonCensusTypeCounted"
115
+ }
116
+ ] });
117
+ this.taxonSets = [...this.taxonSets, deletedTaxonSetId];
118
+ this.props.onChange(updatedFormData);
119
+ return;
120
+ }
121
+ });
122
+ if (observationsExist) {
123
+ return;
124
+ }
125
+ const updatedUnits = currentUnits.filter((unit) => {
126
+ return !unit.taxonSets || !unit.taxonSets.includes(deletedTaxonSetId);
127
+ });
128
+ const updatedFormData = Object.assign(Object.assign({}, formData), { units: updatedUnits });
129
+ this.props.onChange(updatedFormData);
130
+ });
131
+ }
132
+ if (addedTaxonSets.length > 0) {
133
+ const currentUnits = Array.isArray((_c = this.props.formData) === null || _c === void 0 ? void 0 : _c.units) ? this.props.formData.units : [];
134
+ // if current units include any units with taxon sets that are being added, return to avoid duplicates
135
+ const duplicateUnits = currentUnits.filter((unit) => {
136
+ return unit.taxonSets && unit.taxonSets.some((taxonSetId) => addedTaxonSets.includes(taxonSetId));
137
+ });
138
+ if (duplicateUnits.length > 0) {
139
+ return;
140
+ }
141
+ const results = yield this.fetchTaxaFromSet(this.props, addedTaxonSets);
142
+ const newUnits = results.map((result) => {
143
+ return {
144
+ identifications: [{
145
+ taxon: result.scientificName,
146
+ taxonID: result.id,
147
+ taxonVerbatim: result.vernacularName
148
+ }],
149
+ informalTaxonGroups: result.informalTaxonGroups || [],
150
+ taxonSets: result.taxonSets || []
151
+ };
152
+ });
153
+ const updatedFormData = Object.assign(Object.assign({}, formData), { units: [...currentUnits, ...newUnits] });
154
+ this.props.onChange(updatedFormData);
155
+ }
156
+ });
157
+ }
158
+ static getName() {
159
+ return "TaxonSetPopulatorField";
160
+ }
161
+ getStateFromProps() {
162
+ return { onChange: this.onChange };
163
+ }
164
+ fetchTaxaFromSet(props, taxonSets) {
165
+ return __awaiter(this, void 0, void 0, function* () {
166
+ var _a;
167
+ const apiClient = (_a = props.formContext) === null || _a === void 0 ? void 0 : _a.apiClient;
168
+ if (!apiClient) {
169
+ return [];
170
+ }
171
+ try {
172
+ const response = yield apiClient.post("/taxa", {
173
+ query: {
174
+ pageSize: 1000,
175
+ selectedFields: ["id", "scientificName", "vernacularName", "informalTaxonGroups", "taxonSets"]
176
+ }
177
+ }, {
178
+ taxonSets
179
+ });
180
+ if (!response.results || !Array.isArray(response.results)) {
181
+ return [];
182
+ }
183
+ return response.results;
184
+ }
185
+ catch (error) {
186
+ return [];
187
+ }
188
+ });
189
+ }
190
+ };
191
+ TaxonSetPopulatorField.propTypes = {
192
+ uiSchema: PropTypes.shape({
193
+ "ui:options": PropTypes.shape({
194
+ props: PropTypes.oneOfType([PropTypes.arrayOf(propsPropType), propsPropType])
195
+ }),
196
+ uiSchema: PropTypes.object
197
+ }).isRequired,
198
+ schema: PropTypes.shape({
199
+ type: PropTypes.oneOf(["array", "object"])
200
+ }).isRequired,
201
+ formData: PropTypes.oneOfType([PropTypes.array, PropTypes.object]).isRequired
202
+ };
203
+ TaxonSetPopulatorField = __decorate([
204
+ VirtualSchemaField_1.default
205
+ ], TaxonSetPopulatorField);
206
+ exports.default = TaxonSetPopulatorField;
@@ -917,7 +917,7 @@ class _TaxonWrapper extends React.Component {
917
917
  }
918
918
  }
919
919
  this.setState(Object.assign(Object.assign({}, state), { higherThanOrder: !state.order && !state.family }));
920
- const taxonRanks = yield this.props.formContext.apiClient.get("/metadata/ranges/MX.taxonRankEnum");
920
+ const taxonRanks = (yield this.props.formContext.apiClient.get("/metadata/properties/MX.taxonRank/alt")).results;
921
921
  if (!this.mounted)
922
922
  return;
923
923
  this.setState({ taxonRanks: (0, utils_1.dictionarify)(taxonRanks, function getKey(rank) { return rank.id; }, function getValue(rank) { return rank.value; }) });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luomus/laji-form",
3
- "version": "15.1.89",
3
+ "version": "15.1.92",
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",