@luomus/laji-form 15.1.69 → 15.1.71

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 (39) hide show
  1. package/dist/laji-form.js +1 -1
  2. package/dist/styles.css +2 -2
  3. package/lib/ApiClient.d.ts +66 -21
  4. package/lib/ApiClient.js +174 -68
  5. package/lib/components/LajiForm.d.ts +10 -2
  6. package/lib/components/LajiForm.js +1 -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/CondensedObjectField.js +3 -5
  12. package/lib/components/fields/EnumRangeArrayField.js +1 -1
  13. package/lib/components/fields/GeocoderField.js +67 -79
  14. package/lib/components/fields/ImageArrayField.d.ts +9 -5
  15. package/lib/components/fields/ImageArrayField.js +103 -122
  16. package/lib/components/fields/MapArrayField.js +13 -5
  17. package/lib/components/fields/MapField.d.ts +1 -1
  18. package/lib/components/fields/MapField.js +13 -5
  19. package/lib/components/fields/NamedPlaceChooserField/NamedPlaceChooser.d.ts +2 -1
  20. package/lib/components/fields/NamedPlaceChooserField/NamedPlaceChooserField.d.ts +9 -4
  21. package/lib/components/fields/NamedPlaceChooserField/NamedPlaceChooserField.js +51 -51
  22. package/lib/components/fields/NamedPlaceChooserField/Popup.d.ts +2 -1
  23. package/lib/components/fields/NamedPlaceSaverField.js +22 -18
  24. package/lib/components/fields/PrefixArrayField.js +3 -3
  25. package/lib/components/fields/ScopeField.js +1 -1
  26. package/lib/components/fields/SectionArrayField.js +1 -1
  27. package/lib/components/fields/SingleActiveArrayField.js +7 -7
  28. package/lib/components/fields/SortArrayField.js +1 -1
  29. package/lib/components/fields/TableField.js +2 -2
  30. package/lib/components/fields/UnitCountShorthandField.js +1 -1
  31. package/lib/components/fields/UnitListShorthandArrayField.js +2 -2
  32. package/lib/components/fields/UnitShorthandField.js +14 -18
  33. package/lib/components/templates/ArrayFieldTemplate.js +2 -2
  34. package/lib/components/widgets/AutosuggestWidget.js +77 -66
  35. package/lib/components/widgets/InformalTaxonGroupChooserWidget.js +1 -1
  36. package/lib/components/widgets/InputWithDefaultValueButtonWidget.js +1 -2
  37. package/lib/themes/bs5.js +10 -2
  38. package/lib/validation.js +1 -1
  39. package/package.json +5 -3
@@ -134,10 +134,9 @@ class CondensedObjectField extends React.Component {
134
134
  return Math.max(...oldIndexes, -1) + 1;
135
135
  }
136
136
  render() {
137
- var _a;
138
137
  const SchemaField = this.props.registry.fields.SchemaField;
139
- const { schema, uiSchema, idSchema, errorSchema, formData = {}, required, formContext: { Label, translations } } = this.props;
140
- const uiOptions = (0, utils_1.getUiOptions)(uiSchema);
138
+ const { schema, uiSchema, idSchema, errorSchema, formData = {}, required, disabled, readonly, formContext: { Label, translations, uiSchemaContext } } = this.props;
139
+ const { addFieldPlaceholder = `${translations.AddField}`, confirmDelete = uiSchemaContext.confirmDelete } = (0, utils_1.getUiOptions)(uiSchema);
141
140
  const childProps = this.state.selectedFields.map(field => {
142
141
  let childSchema = schema.properties[field.name];
143
142
  let childUiSchema = uiSchema[field.name] || {};
@@ -162,14 +161,13 @@ class CondensedObjectField extends React.Component {
162
161
  value: prop,
163
162
  label: schema.properties[prop].title || prop,
164
163
  }));
165
- const addFieldPlaceholder = (_a = uiOptions.addFieldPlaceholder) !== null && _a !== void 0 ? _a : `${translations.AddField}`;
166
164
  return (React.createElement(React.Fragment, null,
167
165
  React.createElement(Label, { label: this.props.schema.title, required: required || uiSchema["ui:required"], id: this.props.idSchema.$id, uiSchema: this.props.uiSchema }),
168
166
  childProps.map((props, idx) => React.createElement("div", { key: idx, className: "laji-form-field-template-item condensed-object-field-item" },
169
167
  React.createElement("div", { className: "laji-form-field-template-schema" },
170
168
  React.createElement(SchemaField, Object.assign({}, this.props, props, { key: idx, onChange: this.onFieldChange(idx) }))),
171
169
  React.createElement("div", { className: "laji-form-field-template-buttons" },
172
- React.createElement(components_1.DeleteButton, { id: props.idSchema.$id, onClick: this.onFieldDelete(idx), translations: translations })))),
170
+ React.createElement(components_1.DeleteButton, { id: props.idSchema.$id, onClick: this.onFieldDelete(idx), translations: translations, confirm: confirmDelete, disabled: disabled || readonly })))),
173
171
  React.createElement(SelectWidget_1.default, { key: childProps.length, options: { enumOptions: selectableFieldEnums, placeholder: addFieldPlaceholder }, onChange: this.onSelectFieldChange, includeEmpty: true, schema: {}, id: `${idSchema.$id}_field_select`, formContext: this.props.formContext, disabled: this.props.disabled, readonly: this.props.readonly })));
174
172
  }
175
173
  }
@@ -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.fetchCached(`/metadata/ranges/${range}`);
63
+ const enums = yield props.formContext.apiClient.get(`/metadata/ranges/${range}`);
64
64
  return enums.map(({ value }) => ({ value, label: value }));
65
65
  }), [props.formContext.apiClient, range]);
66
66
  const { Label } = props.formContext;
@@ -195,78 +195,73 @@ let GeocoderField = class GeocoderField extends React.Component {
195
195
  responseField: "long_name"
196
196
  }
197
197
  };
198
- if (response.status === "OK") {
199
- const found = {};
200
- Object.keys(parsers).forEach(field => {
201
- const parser = parsers[field];
202
- parser.type.some((type, typeIdx) => {
203
- response.results.forEach(result => result.address_components.forEach(addressComponent => {
204
- if (addressComponent.types.includes(type)) {
205
- if (!found[field])
206
- found[field] = {};
207
- if (!found[field][typeIdx])
208
- found[field][typeIdx] = {};
209
- const responseField = addressComponent[parser.responseField] ? parser.responseField : "short_name";
210
- found[field][typeIdx][addressComponent[responseField]] = true;
211
- }
212
- }));
213
- return found[field] && found[field][typeIdx];
214
- });
198
+ const found = {};
199
+ Object.keys(parsers).forEach(field => {
200
+ const parser = parsers[field];
201
+ parser.type.some((type, typeIdx) => {
202
+ response.results.forEach(result => result.address_components.forEach(addressComponent => {
203
+ if (addressComponent.types.includes(type)) {
204
+ if (!found[field])
205
+ found[field] = {};
206
+ if (!found[field][typeIdx])
207
+ found[field][typeIdx] = {};
208
+ const responseField = addressComponent[parser.responseField] ? parser.responseField : "short_name";
209
+ found[field][typeIdx][addressComponent[responseField]] = true;
210
+ }
211
+ }));
212
+ return found[field] && found[field][typeIdx];
215
213
  });
216
- Object.keys(parsers).forEach(field => {
217
- if (!fieldByKeys[field] || !this.props.schema.properties[field]) {
218
- return;
219
- }
220
- if (found[field]) {
221
- const keys = Object.keys(found[field]);
222
- const responseForField = found[field][keys[0]];
223
- Object.keys(responseForField).forEach(value => {
224
- // If target field is array.
225
- if (this.props.schema.properties[field].type === "array") {
226
- const temp = Array.from((this.props.formData || {})[field] || []);
227
- // Find correct enum from fieldOptions.
228
- const fieldOptions = this.props.uiSchema["ui:options"].fieldOptions;
229
- const enumField = fieldOptions[fieldOptions.findIndex(element => {
230
- return element.field === field;
231
- })].enum;
232
- // Find enum value from key (eg. municipalityName --> municipalityId).
233
- const _enum = this.props.formContext.uiSchemaContext[enumField].oneOf;
234
- const enumValue = _enum.find(item => item.title === value).const;
235
- // Push enum value to changes.
236
- if (enumValue !== undefined) {
237
- !temp.includes(enumValue) && temp.push(enumValue);
238
- changes[field] = temp;
239
- }
240
- }
241
- else {
242
- changes[field] = join(changes[field], value);
214
+ });
215
+ Object.keys(parsers).forEach(field => {
216
+ if (!fieldByKeys[field] || !this.props.schema.properties[field]) {
217
+ return;
218
+ }
219
+ if (found[field]) {
220
+ const keys = Object.keys(found[field]);
221
+ const responseForField = found[field][keys[0]];
222
+ Object.keys(responseForField).forEach(value => {
223
+ // If target field is array.
224
+ if (this.props.schema.properties[field].type === "array") {
225
+ const temp = Array.from((this.props.formData || {})[field] || []);
226
+ // Find correct enum from fieldOptions.
227
+ const fieldOptions = this.props.uiSchema["ui:options"].fieldOptions;
228
+ const enumField = fieldOptions[fieldOptions.findIndex(element => {
229
+ return element.field === field;
230
+ })].enum;
231
+ // Find enum value from key (eg. municipalityName --> municipalityId).
232
+ const _enum = this.props.formContext.uiSchemaContext[enumField].oneOf;
233
+ const enumValue = _enum.find(item => item.title === value).const;
234
+ // Push enum value to changes.
235
+ if (enumValue !== undefined) {
236
+ !temp.includes(enumValue) && temp.push(enumValue);
237
+ changes[field] = temp;
243
238
  }
244
- });
245
- }
246
- else {
247
- changes[field] = (0, utils_1.getDefaultFormState)(this.props.schema.properties[field]);
248
- }
249
- });
250
- if (country && this.props.schema.properties.country && fieldByKeys.country)
251
- changes.country = country;
252
- success(() => {
253
- if (timestamp !== this.promiseTimestamp)
254
- return;
255
- if (this.mounted) {
256
- this.props.onChange(Object.assign(Object.assign({}, (this.props.formData || {})), changes));
257
- }
258
- else {
259
- const pointer = this.props.formContext.services.ids.getJSONPointerFromLajiFormIdAndFormDataAndIdSchemaId(this.props.idSchema.$id, (0, utils_1.getFieldUUID)(this.props));
260
- const newFormData = Object.assign(Object.assign({}, (0, utils_1.parseJSONPointer)(lajiFormInstance.getFormData(), pointer)), changes);
261
- lajiFormInstance.onChange((0, utils_1.updateSafelyWithJSONPointer)(lajiFormInstance.getFormData(), newFormData, pointer));
262
- }
263
- if (callback)
264
- callback();
265
- });
266
- }
267
- else if (country) {
268
- fetchForeign();
269
- }
239
+ }
240
+ else {
241
+ changes[field] = join(changes[field], value);
242
+ }
243
+ });
244
+ }
245
+ else {
246
+ changes[field] = (0, utils_1.getDefaultFormState)(this.props.schema.properties[field]);
247
+ }
248
+ });
249
+ if (country && this.props.schema.properties.country && fieldByKeys.country)
250
+ changes.country = country;
251
+ success(() => {
252
+ if (timestamp !== this.promiseTimestamp)
253
+ return;
254
+ if (this.mounted) {
255
+ this.props.onChange(Object.assign(Object.assign({}, (this.props.formData || {})), changes));
256
+ }
257
+ else {
258
+ const pointer = this.props.formContext.services.ids.getJSONPointerFromLajiFormIdAndFormDataAndIdSchemaId(this.props.idSchema.$id, (0, utils_1.getFieldUUID)(this.props));
259
+ const newFormData = Object.assign(Object.assign({}, (0, utils_1.parseJSONPointer)(lajiFormInstance.getFormData(), pointer)), changes);
260
+ lajiFormInstance.onChange((0, utils_1.updateSafelyWithJSONPointer)(lajiFormInstance.getFormData(), newFormData, pointer));
261
+ }
262
+ if (callback)
263
+ callback();
264
+ });
270
265
  };
271
266
  const fetchForeign = () => {
272
267
  if (!props.formContext.googleApiKey)
@@ -292,15 +287,8 @@ let GeocoderField = class GeocoderField extends React.Component {
292
287
  }, 30 * 1000);
293
288
  !bounds.overlaps(globals_1.FINLAND_BOUNDS)
294
289
  ? fetchForeign()
295
- : this.props.formContext.apiClient.fetchRaw("/coordinates/location", undefined, {
296
- method: "POST",
297
- headers: {
298
- "accept": "application/json",
299
- "content-type": "application/json"
300
- },
301
- body: JSON.stringify(geometry)
302
- }).then(response => response.json()).then(handleResponse(props.formContext.translations.Finland, "municipality", "biologicalProvince", "biogeographicalProvince")).catch((e) => {
303
- fail(e.message);
290
+ : this.props.formContext.apiClient.post("/coordinates/location", undefined, geometry).then().then(handleResponse(props.formContext.translations.Finland, "municipality", "biologicalProvince", "biogeographicalProvince")).catch((e) => {
291
+ fail(typeof e === "string" ? e : e.message);
304
292
  });
305
293
  }));
306
294
  };
@@ -16,6 +16,10 @@ interface MediaMetadataSchema {
16
16
  intellectualOwner?: string;
17
17
  intellectualRights?: string;
18
18
  }
19
+ interface ProcessedExifData {
20
+ formData?: any;
21
+ defaultMediaMetadata?: any;
22
+ }
19
23
  export default class ImageArrayField extends React.Component<FieldProps<any, JSONSchemaArray<JSONSchemaObject>>, ImageArrayFieldState> {
20
24
  ALLOWED_FILE_TYPES: string[];
21
25
  ACCEPT_FILE_TYPES: string[];
@@ -89,18 +93,18 @@ export declare function MediaArrayField<LFC extends Constructor<React.Component<
89
93
  onHideMediaAddModal: () => void;
90
94
  renderMediaAddModal: () => JSX.Element | null;
91
95
  onAlertOk: () => void;
92
- parseExif: (files: File[]) => undefined | Promise<any>;
96
+ parseExif: (files: File[]) => Promise<ProcessedExifData>;
93
97
  sideEffects: (formData: any) => void;
94
98
  onFileFormChange: (files: File[]) => void;
95
99
  getContainerId: () => number | "root";
96
- saveMedias(files: File[]): Promise<any[] | undefined>;
100
+ saveMedias(files: File[], exifDataPromise: Promise<ProcessedExifData>): Promise<any[] | undefined>;
97
101
  addNameToDataURL: (dataURL: string, name: string) => string;
98
102
  processFiles: (files: File[]) => Promise<ProcessedFile[]>;
99
103
  processFile: (file: File) => Promise<ProcessedFile>;
100
104
  onMediaMetadataUpdate: ({ formData }: {
101
105
  formData: any;
102
- }) => void;
103
- getMetadataPromise: () => Promise<MediaMetadataSchema>;
106
+ }) => Promise<void>;
107
+ getMetadataPromise: (exifDataPromise: Promise<ProcessedExifData>) => Promise<MediaMetadataSchema>;
104
108
  getMaxFileSizeAsString: () => string;
105
109
  getAllowedMediaFormatsTranslationKey: () => "AllowedFileFormat" | "AllowedFileFormats";
106
110
  getAllowedMediaFormatsAsString: () => string;
@@ -170,7 +174,7 @@ export declare class Thumbnail extends React.PureComponent<ThumbnailProps, Thumb
170
174
  componentDidMount(): void;
171
175
  componentWillUnmount(): void;
172
176
  UNSAFE_componentWillReceiveProps(props: ThumbnailProps): void;
173
- updateURL: ({ id, apiClient, apiEndpoint }: ThumbnailProps) => void;
177
+ updateURL: ({ id, apiClient, apiEndpoint }: ThumbnailProps) => Promise<void>;
174
178
  render(): JSX.Element | null;
175
179
  }
176
180
  export {};
@@ -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)
@@ -162,7 +171,7 @@ function MediaArrayField(ComposedComponent) {
162
171
  const item = this.props.formData[i];
163
172
  this.setState({ metadataModalOpen: i });
164
173
  this.fetching = item;
165
- this.apiClient.fetch(`/${this.ENDPOINT}/${item}`).then((response) => {
174
+ this.apiClient.get(`/${this.ENDPOINT}/{id}`, { path: { id: item } }).then((response) => {
166
175
  if (response.id !== this.fetching)
167
176
  return;
168
177
  this._context.metadatas[item] = response;
@@ -172,10 +181,11 @@ function MediaArrayField(ComposedComponent) {
172
181
  this.onMediaRmClick = (i) => () => {
173
182
  const id = this.props.formData[i];
174
183
  this.props.onChange((0, immutability_helper_1.default)(this.props.formData, { $splice: [[i, 1]] }));
175
- this.apiClient.fetch(`/${this.ENDPOINT}/${id}`, undefined, {
176
- method: "DELETE",
177
- failSilently: true
178
- });
184
+ try {
185
+ this.apiClient.delete(`/${this.ENDPOINT}/{id}`, { path: { id } });
186
+ }
187
+ catch (e) {
188
+ }
179
189
  };
180
190
  this.hideMetadataModal = () => this.setState({ metadataModalOpen: false, metadataSaveSuccess: undefined });
181
191
  this.onMetadataFormChange = (formData) => this.setState({ modalMetadata: formData });
@@ -185,7 +195,7 @@ function MediaArrayField(ComposedComponent) {
185
195
  const metadataForm = this.state.metadataForm || {};
186
196
  if (typeof metadataModalOpen === "number" && !this.state.metadataForm) {
187
197
  const { metadataFormId = this.METADATA_FORM_ID } = (0, utils_1.getUiOptions)(this.props.uiSchema);
188
- this.apiClient.fetchCached(`/forms/${metadataFormId}`, { lang, format: "schema" })
198
+ this.apiClient.get("/forms/{id}", { path: { id: metadataFormId }, query: { lang, format: "schema" } })
189
199
  .then(metadataForm => {
190
200
  if (this.mounted) {
191
201
  this.setState({ metadataForm });
@@ -250,7 +260,7 @@ function MediaArrayField(ComposedComponent) {
250
260
  this.parseExif = (files) => {
251
261
  const { exifParsers = [] } = (0, utils_1.getUiOptions)(this.props.uiSchema);
252
262
  if (!exifParsers)
253
- return;
263
+ return Promise.resolve({});
254
264
  const found = exifParsers.reduce((found, { parse }) => {
255
265
  found[parse] = false;
256
266
  return found;
@@ -316,15 +326,19 @@ function MediaArrayField(ComposedComponent) {
316
326
  const lajiFormInstance = this.props.formContext.services.rootInstance;
317
327
  const schema = lajiFormInstance.getSchema();
318
328
  let formData = lajiFormInstance.getFormData();
329
+ let defaultMediaMetadata = {};
319
330
  exifParsers.filter((f) => f.type === "event" || found[f.parse]).forEach(({ field, parse, type, eventName }) => {
320
331
  if (type === "mutate") {
321
332
  formData = (0, utils_1.updateFormDataWithJSONPointer)({ formData, schema, registry }, found[parse], field);
322
333
  }
334
+ if (type === "mutateMetadata") {
335
+ defaultMediaMetadata = (0, utils_1.updateSafelyWithJSONPointer)(defaultMediaMetadata, found[parse], field);
336
+ }
323
337
  if (type === "event") {
324
338
  this.props.formContext.services.customEvents.send(`root_${(0, utils_1.JSONPointerToId)(field)}`, eventName, found[parse], undefined, { bubble: false });
325
339
  }
326
340
  });
327
- return formData;
341
+ return { formData, defaultMediaMetadata };
328
342
  });
329
343
  };
330
344
  this.sideEffects = (formData) => {
@@ -354,14 +368,18 @@ function MediaArrayField(ComposedComponent) {
354
368
  }
355
369
  };
356
370
  this.onFileFormChange = (files) => {
357
- var _a;
358
371
  if (this.state.addModal) {
359
372
  this.setState({ addModal: undefined });
360
373
  }
361
- (_a = this.parseExif(files)) === null || _a === void 0 ? void 0 : _a.then(this.sideEffects);
374
+ const exifDataPromise = this.parseExif(files);
375
+ exifDataPromise.then(data => {
376
+ if (data.formData) {
377
+ this.sideEffects(data.formData);
378
+ }
379
+ });
362
380
  const id = this.getContainerId();
363
381
  const lajiFormInstance = this.props.formContext.services.rootInstance;
364
- const saveAndOnChange = () => this.saveMedias(files).then(mediaIds => {
382
+ const saveAndOnChange = () => this.saveMedias(files, exifDataPromise).then(mediaIds => {
365
383
  if (!lajiFormInstance.isMounted() || !mediaIds) {
366
384
  return;
367
385
  }
@@ -422,16 +440,10 @@ function MediaArrayField(ComposedComponent) {
422
440
  reader.readAsDataURL(file);
423
441
  });
424
442
  };
425
- this.onMediaMetadataUpdate = ({ formData }) => {
443
+ this.onMediaMetadataUpdate = (_a) => __awaiter(this, [_a], void 0, function* ({ formData }) {
426
444
  this.props.formContext.services.blocker.push();
427
- this.apiClient.fetch(`/${this.ENDPOINT}/${formData.id}`, undefined, {
428
- method: "PUT",
429
- headers: {
430
- "accept": "application/json",
431
- "content-type": "application/json"
432
- },
433
- body: JSON.stringify(formData)
434
- }).then(() => {
445
+ try {
446
+ yield this.apiClient.put(`/${this.ENDPOINT}/{id}`, { path: { id: formData.id } }, formData);
435
447
  this.props.formContext.services.blocker.pop();
436
448
  const notify = () => this.props.formContext.notifier.success(this.props.formContext.translations.SaveSuccess);
437
449
  if (this.mounted) {
@@ -440,20 +452,24 @@ function MediaArrayField(ComposedComponent) {
440
452
  else {
441
453
  notify();
442
454
  }
443
- }).catch(() => {
455
+ }
456
+ catch (e) {
444
457
  this.props.formContext.services.blocker.pop();
445
458
  this.mounted && this.setState({ metadataSaveSuccess: false });
446
- });
447
- };
448
- this.getMetadataPromise = () => {
459
+ }
460
+ });
461
+ this.getMetadataPromise = (exifDataPromise) => {
449
462
  let mediaMetadata = this.props.formContext.mediaMetadata
450
463
  || { intellectualRights: "MZ.intellectualRightsARR" };
451
464
  const MACode = this.props.formContext.uiSchemaContext.creator;
452
- return ("capturerVerbatim" in mediaMetadata)
453
- ? Promise.resolve(Object.assign(Object.assign({}, mediaMetadata), { capturerVerbatim: [mediaMetadata.capturerVerbatim] }))
465
+ const metadataPromise = ("capturerVerbatim" in mediaMetadata)
466
+ ? Promise.resolve(Object.assign(Object.assign({}, mediaMetadata), { capturerVerbatim: Array.isArray(mediaMetadata.capturerVerbatim) ? mediaMetadata.capturerVerbatim : [mediaMetadata.capturerVerbatim] }))
454
467
  : MACode
455
- ? this.apiClient.fetchCached(`/person/by-id/${MACode}`).then(({ fullName = MACode }) => (Object.assign(Object.assign({ capturerVerbatim: Array.isArray(fullName) ? fullName : [fullName] }, mediaMetadata), { intellectualOwner: fullName }))).catch(() => Promise.resolve(mediaMetadata))
456
- : mediaMetadata;
468
+ ? this.apiClient.get("/person/by-id/{personId}", { path: { personId: MACode } }).then(({ fullName = MACode }) => (Object.assign(Object.assign({ capturerVerbatim: Array.isArray(fullName) ? fullName : [fullName] }, mediaMetadata), { intellectualOwner: fullName }))).catch(() => Promise.resolve(mediaMetadata))
469
+ : Promise.resolve(mediaMetadata);
470
+ return Promise.all([exifDataPromise, metadataPromise]).then(([exifData, metadata]) => {
471
+ return Object.assign(Object.assign({}, exifData.defaultMediaMetadata), metadata);
472
+ });
457
473
  };
458
474
  this.getMaxFileSizeAsString = () => {
459
475
  let maxSize = this.MAX_FILE_SIZE.toString().substring(0, this.MAX_FILE_SIZE.toString().length - 6);
@@ -566,106 +582,68 @@ function MediaArrayField(ComposedComponent) {
566
582
  this.renderMetadataModal(),
567
583
  this.renderMediaAddModal()))));
568
584
  }
569
- saveMedias(files) {
570
- const containerId = this.getContainerId();
571
- let tmpMedias;
572
- const fail = (translationKey, additionalInfo = "") => {
573
- const translation = (Array.isArray(translationKey) ? translationKey : [translationKey])
574
- .map((key) => this.props.formContext.translations[key])
575
- .join(". ");
576
- throw `${translation} ${additionalInfo}`;
577
- };
578
- return this.processFiles(files).then(processedFiles => {
579
- let invalidFile = (files.length <= 0);
580
- let fileTooLarge = false;
581
- let noValidData = true;
582
- if (!this._context.tmpMedias[containerId]) {
583
- this._context.tmpMedias[containerId] = {};
584
- }
585
- tmpMedias = processedFiles.map(f => {
586
- mediaUuid++;
587
- this._context.tmpMedias[containerId][mediaUuid] = f.dataURL;
588
- return mediaUuid;
589
- });
590
- this.mounted && this.setState({ tmpMedias: [...(this.state.tmpMedias || []), ...tmpMedias] });
591
- const formDataBody = files.reduce((body, file) => {
592
- if (!this.ALLOWED_FILE_TYPES.includes(file.type)) {
593
- invalidFile = true;
585
+ saveMedias(files, exifDataPromise) {
586
+ return __awaiter(this, void 0, void 0, function* () {
587
+ const containerId = this.getContainerId();
588
+ let tmpMedias = [];
589
+ const fail = (translationKey, additionalInfo = "") => {
590
+ const translation = (Array.isArray(translationKey) ? translationKey : [translationKey])
591
+ .map((key) => this.props.formContext.translations[key])
592
+ .join(". ");
593
+ throw `${translation} ${additionalInfo}`;
594
+ };
595
+ try {
596
+ const processedFiles = yield this.processFiles(files);
597
+ let invalidFile = (files.length <= 0);
598
+ let fileTooLarge = false;
599
+ let noValidData = true;
600
+ if (!this._context.tmpMedias[containerId]) {
601
+ this._context.tmpMedias[containerId] = {};
594
602
  }
595
- else if (file.size > this.MAX_FILE_SIZE) {
596
- fileTooLarge = true;
603
+ tmpMedias = processedFiles.map(f => {
604
+ mediaUuid++;
605
+ this._context.tmpMedias[containerId][mediaUuid] = f.dataURL;
606
+ return mediaUuid;
607
+ });
608
+ this.mounted && this.setState({ tmpMedias: [...(this.state.tmpMedias || []), ...tmpMedias] });
609
+ const formData = files.reduce((body, file) => {
610
+ if (!this.ALLOWED_FILE_TYPES.includes(file.type)) {
611
+ invalidFile = true;
612
+ }
613
+ else if (file.size > this.MAX_FILE_SIZE) {
614
+ fileTooLarge = true;
615
+ }
616
+ else {
617
+ body.append("data", file);
618
+ noValidData = false;
619
+ }
620
+ return body;
621
+ }, new FormData());
622
+ if (noValidData && invalidFile) {
623
+ fail(this.getAllowedMediaFormatsTranslationKey(), this.getAllowedMediaFormatsAsString() + ".");
624
+ return;
597
625
  }
598
- else {
599
- body.append("data", file);
600
- noValidData = false;
626
+ else if (noValidData && fileTooLarge) {
627
+ fail("AllowedFileSize", this.getMaxFileSizeAsString() + ".");
628
+ return;
601
629
  }
602
- return body;
603
- }, new FormData());
604
- if (noValidData && invalidFile) {
605
- fail(this.getAllowedMediaFormatsTranslationKey(), this.getAllowedMediaFormatsAsString() + ".");
606
- return;
607
- }
608
- else if (noValidData && fileTooLarge) {
609
- fail("AllowedFileSize", this.getMaxFileSizeAsString() + ".");
610
- return;
611
- }
612
- else {
613
- return this.apiClient.fetchRaw(`/${this.ENDPOINT}`, undefined, {
614
- method: "POST",
615
- body: formDataBody
630
+ const tmpMediaEntities = yield this.apiClient.post(`/${this.ENDPOINT}`, undefined, formData);
631
+ const mediaMetadata = yield this.getMetadataPromise(exifDataPromise);
632
+ const mediaEntities = yield Promise.all(tmpMediaEntities.map((item) => this.apiClient.post(`/${this.ENDPOINT}/{id}`, { path: { id: item.id } }, mediaMetadata)));
633
+ const ids = mediaEntities.map((item) => item ? item.id : undefined).filter(item => item !== undefined);
634
+ tmpMedias.forEach(id => {
635
+ delete this._context.tmpMedias[containerId][id];
616
636
  });
637
+ this.mounted && this.setState({ tmpMedias: this.state.tmpMedias.filter(id => !tmpMedias.includes(id)) });
638
+ return ids;
617
639
  }
618
- }).then(response => {
619
- if (!response)
620
- return;
621
- if (response.status < 400) {
622
- return response.json();
623
- }
624
- else if (response.status === 400) {
625
- fail("InvalidFile");
626
- }
627
- else if (response.status === 503) {
628
- fail("InsufficientSpace");
629
- }
630
- else {
631
- fail(["SomethingWentWrong", "TryAgainLater"]);
632
- }
633
- }).then(response => {
634
- if (!response)
635
- return;
636
- return this.getMetadataPromise().then(mediaMetadata => {
637
- return Promise.all(response.map((item) => {
638
- return this.apiClient.fetchRaw(`/${this.ENDPOINT}/${item.id}`, undefined, {
639
- method: "POST",
640
- headers: {
641
- "accept": "application/json",
642
- "content-type": "application/json"
643
- },
644
- body: JSON.stringify(mediaMetadata)
645
- }).then(response => {
646
- if (response.status < 400) {
647
- return response.json();
648
- }
649
- });
650
- }));
651
- });
652
- }).then(response => {
653
- if (!response)
654
- return;
655
- const ids = response.map((item) => item ? item.id : undefined).filter(item => item !== undefined);
656
- tmpMedias.forEach(id => {
657
- delete this._context.tmpMedias[containerId][id];
658
- });
659
- this.mounted && this.setState({ tmpMedias: this.state.tmpMedias.filter(id => !tmpMedias.includes(id)) });
660
- return ids;
661
- }).catch((e) => {
662
- if (tmpMedias) {
640
+ catch (e) {
663
641
  tmpMedias.forEach(id => {
664
642
  delete this._context.tmpMedias[containerId][id];
665
643
  });
666
644
  this.mounted && this.setState({ tmpMedias: this.state.tmpMedias.filter(id => !tmpMedias.includes(id)) });
645
+ throw e;
667
646
  }
668
- throw e;
669
647
  });
670
648
  }
671
649
  };
@@ -706,15 +684,18 @@ function MediaArrayField(ComposedComponent) {
706
684
  class Thumbnail extends React.PureComponent {
707
685
  constructor(props) {
708
686
  super(props);
709
- this.updateURL = ({ id, apiClient, apiEndpoint = "images" }) => {
687
+ this.updateURL = (_a) => __awaiter(this, [_a], void 0, function* ({ id, apiClient, apiEndpoint = "images" }) {
710
688
  if (!id)
711
689
  return;
712
- apiClient.fetchCached(`/${apiEndpoint}/${id}`, undefined, { failSilently: true }).then((response) => {
690
+ try {
691
+ const response = yield apiClient.get(`/${apiEndpoint}/{id}`, { path: { id } });
713
692
  if (!this.mounted)
714
693
  return;
715
694
  this.setState({ url: response.squareThumbnailURL, linkUrl: response.originalURL });
716
- });
717
- };
695
+ }
696
+ catch (e) {
697
+ }
698
+ });
718
699
  this.state = {};
719
700
  this.updateURL(props);
720
701
  }
@@ -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)
@@ -1053,7 +1062,7 @@ function _MapArrayField(ComposedComponent) {
1053
1062
  constructor(props) {
1054
1063
  super(props);
1055
1064
  this.stretchContainerRef = React.createRef();
1056
- this.geocode = () => {
1065
+ this.geocode = () => __awaiter(this, void 0, void 0, function* () {
1057
1066
  // Zoom map to area. Area ID is accessed from schema field defined in options.areaField
1058
1067
  const item = (this.props.formData || [])[this.state.activeIdx];
1059
1068
  const { areaField } = (0, utils_2.getUiOptions)(this.props.uiSchema);
@@ -1066,11 +1075,10 @@ function _MapArrayField(ComposedComponent) {
1066
1075
  }
1067
1076
  const geometries = this.getGeometries();
1068
1077
  if (geometries.length === 0 && area && area.length > 0) {
1069
- this.props.formContext.apiClient.fetch(`/areas/${area}`, undefined, undefined).then((result) => {
1070
- this.map.geocode(result.name, undefined, 8);
1071
- });
1078
+ const { name } = yield this.props.formContext.apiClient.get(`/areas/${area}`);
1079
+ this.map.geocode(name, undefined, 8);
1072
1080
  }
1073
- };
1081
+ });
1074
1082
  this.computeArea = () => {
1075
1083
  const { activeIdx } = this.state;
1076
1084
  if (activeIdx === undefined)