mapcomplete/UI/ImportFlow/PreviewPanel.ts

111 lines
4.3 KiB
TypeScript
Raw Normal View History

import Combine from "../Base/Combine";
import {UIEventSource} from "../../Logic/UIEventSource";
import UserRelatedState from "../../Logic/State/UserRelatedState";
import Translations from "../i18n/Translations";
import {Utils} from "../../Utils";
import {FlowStep} from "./FlowStep";
import Title from "../Base/Title";
import BaseUIElement from "../BaseUIElement";
import Histogram from "../BigComponents/Histogram";
import Toggleable from "../Base/Toggleable";
import List from "../Base/List";
import CheckBoxes from "../Input/Checkboxes";
/**
* Shows the data to import on a map, asks for the correct layer to be selected
*/
2022-01-24 00:19:01 +01:00
export class PreviewPanel extends Combine implements FlowStep<{ features: { properties: any, geometry: { coordinates: [number, number] } }[] }> {
public readonly IsValid: UIEventSource<boolean>;
2022-01-24 00:19:01 +01:00
public readonly Value: UIEventSource<{ features: { properties: any, geometry: { coordinates: [number, number] } }[] }>
constructor(
state: UserRelatedState,
geojson: { features: { properties: any, geometry: { coordinates: [number, number] } }[] }) {
const t = Translations.t.importHelper;
console.log("Datapanel received", geojson)
const propertyKeys = new Set<string>()
for (const f of geojson.features) {
Object.keys(f.properties).forEach(key => propertyKeys.add(key))
}
2022-01-24 00:19:01 +01:00
const attributeOverview: BaseUIElement[] = []
const n = geojson.features.length;
for (const key of Array.from(propertyKeys)) {
2022-01-24 00:19:01 +01:00
const values = Utils.NoNull(geojson.features.map(f => f.properties[key]))
2022-01-24 00:19:01 +01:00
console.log("There are ",values.length,"features with attribute",key, "namely",values)
const allSame = !values.some(v => v !== values[0])
2022-01-24 00:19:01 +01:00
let countSummary: BaseUIElement
if (values.length === n) {
countSummary = t.allAttributesSame
} else {
countSummary = t.someHaveSame.Subs({
count: values.length,
percentage: Math.floor(100 * values.length / n)
})
}
if (allSame) {
attributeOverview.push(new Title(key + "=" + values[0]))
attributeOverview.push(countSummary)
continue
}
const uniqueCount = new Set(values).size
2022-01-24 01:41:57 +01:00
if (uniqueCount !== values.length && uniqueCount < 15) {
attributeOverview.push()
// There are some overlapping values: histogram time!
2022-01-24 00:19:01 +01:00
let hist: BaseUIElement =
new Combine([
countSummary,
new Histogram(
new UIEventSource<string[]>(values),
"Value",
"Occurence",
{
sortMode: "count-rev"
})
]).SetClass("flex flex-col")
const title = new Title(key + "=*")
if (uniqueCount > 15) {
hist = new Toggleable(title,
hist.SetClass("block")
).Collapse()
2022-01-24 00:19:01 +01:00
} else {
attributeOverview.push(title)
}
2022-01-24 00:19:01 +01:00
attributeOverview.push(hist)
continue
}
2022-01-24 00:19:01 +01:00
2022-01-24 01:41:57 +01:00
// All values are different or too much unique values, we add a boring (but collapsable) list
attributeOverview.push(new Toggleable(
2022-01-24 00:19:01 +01:00
new Title(key + "=*"),
new Combine([
countSummary,
new List(values)
2022-01-24 00:19:01 +01:00
])
))
}
2022-01-24 00:19:01 +01:00
const confirm = new CheckBoxes([t.inspectLooksCorrect])
2022-01-24 00:19:01 +01:00
super([
2022-01-24 00:19:01 +01:00
new Title(t.inspectDataTitle.Subs({count: geojson.features.length})),
2022-01-25 00:48:05 +01:00
"Extra remark: An attribute with 'source' or 'src' will be added as 'source' into the map pin; an attribute 'note' will be added into the map pin as well. These values won't be imported",
...attributeOverview,
confirm
]);
2022-01-24 00:19:01 +01:00
this.Value = new UIEventSource<{ features: { properties: any; geometry: { coordinates: [number, number] } }[] }>(geojson)
this.IsValid = confirm.GetValue().map(selected => selected.length == 1)
2022-01-24 00:19:01 +01:00
}
}