Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions forms/MHL.1158.json
Original file line number Diff line number Diff line change
Expand Up @@ -5141,6 +5141,7 @@
"latitude":"wgs84Latitude",
"longitude":"wgs84Longitude"
},
"confirmChange":true,
"mapOptions":{
"tileLayerName":"taustakartta",
"controls":{
Expand Down
6 changes: 5 additions & 1 deletion src/components/components/FailedBackgroundJobsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export class FailedBackgroundJobsPanel extends React.Component<Props, State> {
this.state = {popped: true};
}

dismissAll = () => {
this.props.formContext.services.submitHooks.removeAll();
};

dismissFailedJob = ({hook, running}: SubmitHook) => (e: React.MouseEvent) => {
e.stopPropagation();
if (running) return;
Expand Down Expand Up @@ -79,7 +83,7 @@ export class FailedBackgroundJobsPanel extends React.Component<Props, State> {
if (!errors.length) return null;

const footer = (
<Button onClick={this.props.formContext.services.submitHooks.removeAll}><Glyphicon glyph="ok"/> {`${translations.Dismiss} ${translations.all}`}</Button>
<Button onClick={this.dismissAll}><Glyphicon glyph="ok"/> {`${translations.Dismiss} ${translations.all}`}</Button>
);

return (
Expand Down
48 changes: 31 additions & 17 deletions src/components/fields/ImageArrayField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import exif from "exifreader";
import { validateLatLng, wgs84Validator } from "@luomus/laji-map/lib/utils";
import moment from "moment";
import { FieldProps, JSONSchemaArray, JSONSchemaObject } from "../../types";
import ApiClient from "../../ApiClient";
import ApiClient, { LajiApiError } from "../../ApiClient";
import ReactContext from "../../ReactContext";
import { getTemplate } from "@rjsf/utils";

Expand Down Expand Up @@ -476,6 +476,18 @@ export function MediaArrayField<LFC extends Constructor<React.Component<FieldPro
};

parseExif = (files: File[]): Promise<ProcessedExifData> => {
const readDateFromFile = (file: File) => {
if (file.lastModified) {
const momentDate = moment(file.lastModified);
if (momentDate.isValid()) {
const date = momentDate.format("YYYY-MM-DDTHH:mm");
if (date) {
found.date = date;
}
}
}
};

const {exifParsers = []} = getUiOptions(this.props.uiSchema);
if (!exifParsers) return Promise.resolve({});

Expand Down Expand Up @@ -509,35 +521,27 @@ export function MediaArrayField<LFC extends Constructor<React.Component<FieldPro
console.info("Reading GPS from EXIF failed", e);
}

const readDateFromFile = () => {
if (file.lastModified) {
const momentDate = moment(file.lastModified);
if (momentDate.isValid()) {
const date = momentDate.format("YYYY-MM-DDTHH:mm");
if (date) {
found.date = date;
}
}
}
};

if ("date" in found) {
try {
const rawDate = tags["DateTimeOriginal"]?.description;
const momentDate = moment(rawDate, "YYYY:MM:DD HH:mm:ss");
if (momentDate.isValid()) {
found.date = momentDate.format("YYYY-MM-DDTHH:mm");
} else {
readDateFromFile();
readDateFromFile(file);
}
} catch (e) {
console.info("Reading date from EXIF failed, trying to read from file", e);
readDateFromFile();
readDateFromFile(file);
}
} else {
readDateFromFile();
readDateFromFile(file);
}
resolve(found);
}).catch(e => {
console.info("Reading EXIF data failed", e);
readDateFromFile(file);
resolve(found);
});
})
);
Expand Down Expand Up @@ -719,7 +723,17 @@ export function MediaArrayField<LFC extends Constructor<React.Component<FieldPro
delete this._context.tmpMedias[containerId][id];
});
this.mounted && this.setState({tmpMedias: this.state.tmpMedias.filter(id => !tmpMedias.includes(id))});
throw e;

let errorMsg: string;
if (typeof e === "string") {
errorMsg = e;
} else if (e instanceof LajiApiError && e.statusCode === 400) {
errorMsg = this.props.formContext.translations.InvalidFile;
} else {
errorMsg = this.props.formContext.translations.RequestFailed;
}

throw errorMsg;
}
}

Expand Down
13 changes: 12 additions & 1 deletion src/components/fields/MapField.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from "react";
import { createPortal, findDOMNode } from "react-dom";
import * as PropTypes from "prop-types";
import { MapComponent } from "./MapArrayField";
import { getUiOptions, isObject } from "../../utils";
import {getUiOptions, hasData, isObject} from "../../utils";
const equals = require("deep-equal");
import Spinner from "react-spinner";
import { Affix, Button, Fullscreen } from "../components";
Expand Down Expand Up @@ -328,6 +328,9 @@ export default class MapField extends React.Component {
};

onChange = (events) => {
const options = getUiOptions(this.props.uiSchema);
const {confirmChange} = options;

let formData;
events.forEach(e => {
switch (e.type) {
Expand All @@ -341,6 +344,14 @@ export default class MapField extends React.Component {
formData = this.getFormDataFromGeometry(undefined);
}
});

if (confirmChange && hasData(this.props.formData) && !equals(formData, this.props.formData)) {
if (!confirm(this.props.formContext.translations.ConfirmLocationChange)) {
this.map.updateDrawData(this.getDrawOptions(this.props));
return;
}
}

this._zoomToDataOnNextTick = true;
this.props.onChange(formData);
};
Expand Down
5 changes: 5 additions & 0 deletions src/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,11 @@
"en": "Pan the location inside the circle",
"sv": "Placera platsen inne i cirkeln"
},
"confirmLocationChange": {
"fi": "Haluatko varmasti muuttaa sijaintia?",
"en": "Are you sure you want to change the location?",
"sv": "Är du säker på att du vill ändra platsen?"
},
"unknown": {
"fi": "Ei tietoa",
"en": "Unknown",
Expand Down
15 changes: 15 additions & 0 deletions test/image-array.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,19 @@ test.describe("Image array", () => {
await expect(form.getImageArrayField("0").$$imgs).toHaveCount(1);
await remove();
});

test("Dismiss all button clears error panel", async () => {
await form.setState({ schema, uiSchema, uiSchemaContext, formData: [] });
const filePath = require("path").resolve(__dirname, "./mock/pixel.png");
const {reject, remove} = await form.setMockResponse("/images", false);

await imgArrayField.$dropzone.locator("input").setInputFiles(filePath);
await reject({message: "Invalid file", statusCode: 400});

await expect(form.failedJobs.$$errors).toHaveCount(1);
await form.failedJobs.$dismissAll.click();
await expect(form.failedJobs.$container).not.toBeVisible();

await remove();
});
});
3 changes: 2 additions & 1 deletion test/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ export class Form {
warnings = this.createValidatorPO("warning");
failedJobs = {
$container: this.$locator.locator(".laji-form-failed-jobs-list"),
$$errors: this.$locator.locator(".laji-form-failed-jobs-list .list-group-item")
$$errors: this.$locator.locator(".laji-form-failed-jobs-list .list-group-item"),
$dismissAll: this.$locator.locator(".laji-form-failed-jobs-list .panel-footer button")
};

$runningJobs = this.$locator.locator(".running-jobs");
Expand Down