Full code cleanup

This commit is contained in:
Pieter Vander Vennet 2022-01-26 21:40:38 +01:00
parent 3a4a2a2016
commit fa971ffbbf
300 changed files with 16352 additions and 19284 deletions

View file

@ -44,22 +44,22 @@ export class AskMetadata extends Combine implements FlowStep<{
inputStyle: "width: 100%"
})
let options : {value: string, shown: BaseUIElement}[]= AllKnownLayouts.layoutsList
let options: { value: string, shown: BaseUIElement }[] = AllKnownLayouts.layoutsList
.filter(th => th.layers.some(l => l.id === params.layer.id))
.filter(th => th.id !== "personal")
.map(th => ({
value: th.id,
shown: th.title
}))
options.splice(0,0, {
options.splice(0, 0, {
shown: new FixedUiElement("Select a theme"),
value: undefined
value: undefined
})
const theme = new DropDown("Which theme should be linked in the note?",options)
ValidatedTextField.InputForType("string", {
const theme = new DropDown("Which theme should be linked in the note?", options)
ValidatedTextField.InputForType("string", {
value: LocalStorageSource.Get("import-helper-theme-text"),
inputStyle: "width: 100%"
})
@ -89,7 +89,7 @@ export class AskMetadata extends Combine implements FlowStep<{
}, [wikilink.GetValue(), source.GetValue(), theme.GetValue()])
this.IsValid = this.Value.map(obj => {
if(obj === undefined){
if (obj === undefined) {
return false;
}
return obj.theme !== undefined && obj.features !== undefined && obj.wikilink !== undefined && obj.intro !== undefined && obj.source !== undefined;

View file

@ -40,12 +40,12 @@ export class CompareToAlreadyExistingNotes extends Combine implements FlowStep<{
tagRenderings: new Map()
}
const layerConfig = known_layers.layers.filter(l => l.id === params.layer.id)[0]
if(layerConfig === undefined){
if (layerConfig === undefined) {
console.error("WEIRD: layer not found in the builtin layer overview")
}
const importLayerJson = new CreateNoteImportLayer(365).convertStrict(convertState, <LayerConfigJson> layerConfig, "CompareToAlreadyExistingNotes")
const importLayerJson = new CreateNoteImportLayer(365).convertStrict(convertState, <LayerConfigJson>layerConfig, "CompareToAlreadyExistingNotes")
const importLayer = new LayerConfig(importLayerJson, "import-layer-dynamic")
const flayer: FilteredLayer = {
appliedFilters: new UIEventSource<Map<string, FilterState>>(new Map<string, FilterState>()),
@ -108,11 +108,11 @@ export class CompareToAlreadyExistingNotes extends Combine implements FlowStep<{
super([
new Title("Compare with already existing 'to-import'-notes"),
new VariableUiElement(
alreadyOpenImportNotes.features.map(notesWithImport => {
if(allNotesWithinBbox.features.data === undefined || allNotesWithinBbox.features.data.length === 0){
return new Loading("Fetching notes from OSM")
alreadyOpenImportNotes.features.map(notesWithImport => {
if (allNotesWithinBbox.features.data === undefined || allNotesWithinBbox.features.data.length === 0) {
return new Loading("Fetching notes from OSM")
}
if(notesWithImport.length === 0){
if (notesWithImport.length === 0) {
return new FixedUiElement("No previous note to import found").SetClass("thanks")
}
return new Combine([
@ -126,7 +126,7 @@ export class CompareToAlreadyExistingNotes extends Combine implements FlowStep<{
).SetClass("w-full"),
comparisonMap,
]).SetClass("flex flex-col")
}, [allNotesWithinBbox.features])
),
@ -140,15 +140,15 @@ export class CompareToAlreadyExistingNotes extends Combine implements FlowStep<{
}))
this.IsValid = alreadyOpenImportNotes.features.map(ff => {
if(allNotesWithinBbox.features.data.length === 0){
if (allNotesWithinBbox.features.data.length === 0) {
// Not yet loaded
return false
}
if(ff.length == 0){
if (ff.length == 0) {
// No import notes at all
return true;
}
return partitionedImportPoints.data.noNearby.length > 0; // at least _something_ can be imported
}, [partitionedImportPoints, allNotesWithinBbox.features])
}

View file

@ -32,7 +32,7 @@ import {ImportUtils} from "./ImportUtils";
/**
* Given the data to import, the bbox and the layer, will query overpass for similar items
*/
export default class ConflationChecker extends Combine implements FlowStep<{features: any[], layer: LayerConfig}> {
export default class ConflationChecker extends Combine implements FlowStep<{ features: any[], layer: LayerConfig }> {
public readonly IsValid
public readonly Value
@ -40,12 +40,12 @@ export default class ConflationChecker extends Combine implements FlowStep<{feat
constructor(
state,
params: { bbox: BBox, layer: LayerConfig, geojson: any }) {
const bbox = params.bbox.padAbsolute(0.0001)
const layer = params.layer;
const toImport = params.geojson;
let overpassStatus = new UIEventSource<{ error: string } | "running" | "success" | "idle" | "cached" >("idle")
let overpassStatus = new UIEventSource<{ error: string } | "running" | "success" | "idle" | "cached">("idle")
const cacheAge = new UIEventSource<number>(undefined);
const fromLocalStorage = IdbLocalStorage.Get<[any, Date]>("importer-overpass-cache-" + layer.id, {
whenLoaded: (v) => {
@ -53,7 +53,7 @@ export default class ConflationChecker extends Combine implements FlowStep<{feat
console.log("Loaded from local storage:", v)
const [geojson, date] = v;
const timeDiff = (new Date().getTime() - date.getTime()) / 1000;
console.log("Loaded ", geojson.features.length," features; cache is ", timeDiff, "seconds old")
console.log("Loaded ", geojson.features.length, " features; cache is ", timeDiff, "seconds old")
cacheAge.setData(timeDiff)
if (timeDiff < 24 * 60 * 60) {
// Recently cached!
@ -69,18 +69,20 @@ export default class ConflationChecker extends Combine implements FlowStep<{feat
console.log("Loading from overpass!")
overpassStatus.setData("running")
overpass.queryGeoJson(bbox).then(
([data, date] ) => {
console.log("Received overpass-data: ", data.features.length,"features are loaded at ", date);
([data, date]) => {
console.log("Received overpass-data: ", data.features.length, "features are loaded at ", date);
overpassStatus.setData("success")
fromLocalStorage.setData([data, date])
},
(error) => {overpassStatus.setData({error})})
},
(error) => {
overpassStatus.setData({error})
})
}
});
const geojson : UIEventSource<any> = fromLocalStorage.map(d => {
const geojson: UIEventSource<any> = fromLocalStorage.map(d => {
if (d === undefined) {
return undefined
}
@ -102,21 +104,20 @@ export default class ConflationChecker extends Combine implements FlowStep<{feat
})
osmLiveData.SetClass("w-full").SetStyle("height: 500px")
const preview = new StaticFeatureSource(geojson.map(geojson => {
if(geojson?.features === undefined){
if (geojson?.features === undefined) {
return []
}
const zoomedEnough: boolean = osmLiveData.location.data.zoom >= Number(zoomLevel.GetValue().data)
if(!zoomedEnough){
if (!zoomedEnough) {
return []
}
const bounds = osmLiveData.bounds.data
return geojson.features.filter(f => BBox.get(f).overlapsWith(bounds))
}, [osmLiveData.bounds, zoomLevel.GetValue()]), false);
new ShowDataLayer({
layerToShow:new LayerConfig(currentview),
layerToShow: new LayerConfig(currentview),
state,
leafletMap: osmLiveData.leafletMap,
popup: undefined,
@ -128,7 +129,7 @@ export default class ConflationChecker extends Combine implements FlowStep<{feat
new ShowDataLayer({
layerToShow:layer,
layerToShow: layer,
state,
leafletMap: osmLiveData.leafletMap,
popup: (tags, layer) => new FeatureInfoBox(tags, layer, state),
@ -137,18 +138,18 @@ export default class ConflationChecker extends Combine implements FlowStep<{feat
})
new ShowDataLayer({
layerToShow:new LayerConfig(import_candidate),
layerToShow: new LayerConfig(import_candidate),
state,
leafletMap: osmLiveData.leafletMap,
popup: (tags, layer) => new FeatureInfoBox(tags, layer, state),
zoomToFeatures: false,
features: new StaticFeatureSource(toImport.features, false)
})
const nearbyCutoff = ValidatedTextField.InputForType("pnat")
nearbyCutoff.SetClass("ml-1 border border-black")
nearbyCutoff.GetValue().syncWith(LocalStorageSource.Get("importer-cutoff", "25"), true)
const matchedFeaturesMap = Minimap.createMiniMap({
allowMoving: true,
background
@ -157,21 +158,21 @@ export default class ConflationChecker extends Combine implements FlowStep<{feat
// Featuresource showing OSM-features which are nearby a toImport-feature
const nearbyFeatures = new StaticFeatureSource(geojson.map(osmData => {
if(osmData?.features === undefined){
if (osmData?.features === undefined) {
return []
}
const maxDist = Number(nearbyCutoff.GetValue().data)
return osmData.features.filter(f =>
toImport.features.some(imp =>
maxDist >= GeoOperations.distanceBetween(imp.geometry.coordinates, GeoOperations.centerpointCoordinates(f))) )
return osmData.features.filter(f =>
toImport.features.some(imp =>
maxDist >= GeoOperations.distanceBetween(imp.geometry.coordinates, GeoOperations.centerpointCoordinates(f))))
}, [nearbyCutoff.GetValue()]), false);
const paritionedImport = ImportUtils.partitionFeaturesIfNearby(toImport, geojson, nearbyCutoff.GetValue().map(Number));
// Featuresource showing OSM-features which are nearby a toImport-feature
const toImportWithNearby = new StaticFeatureSource(paritionedImport.map(els =>els?.hasNearby ?? []), false);
const toImportWithNearby = new StaticFeatureSource(paritionedImport.map(els => els?.hasNearby ?? []), false);
new ShowDataLayer({
layerToShow:layer,
layerToShow: layer,
state,
leafletMap: matchedFeaturesMap.leafletMap,
popup: (tags, layer) => new FeatureInfoBox(tags, layer, state),
@ -180,47 +181,47 @@ export default class ConflationChecker extends Combine implements FlowStep<{feat
})
new ShowDataLayer({
layerToShow:new LayerConfig(import_candidate),
layerToShow: new LayerConfig(import_candidate),
state,
leafletMap: matchedFeaturesMap.leafletMap,
popup: (tags, layer) => new FeatureInfoBox(tags, layer, state),
zoomToFeatures: false,
features: toImportWithNearby
})
const conflationMaps = new Combine([
const conflationMaps = new Combine([
new VariableUiElement(
geojson.map(geojson => {
if (geojson === undefined) {
return undefined;
}
return new SubtleButton(Svg.download_svg(), "Download the loaded geojson from overpass").onClick(() => {
Utils.offerContentsAsDownloadableFile(JSON.stringify(geojson, null, " "), "mapcomplete-" + layer.id + ".geojson", {
mimetype: "application/json+geo"
})
});
})),
geojson.map(geojson => {
if (geojson === undefined) {
return undefined;
}
return new SubtleButton(Svg.download_svg(), "Download the loaded geojson from overpass").onClick(() => {
Utils.offerContentsAsDownloadableFile(JSON.stringify(geojson, null, " "), "mapcomplete-" + layer.id + ".geojson", {
mimetype: "application/json+geo"
})
});
})),
new VariableUiElement(cacheAge.map(age => {
if(age === undefined){
if (age === undefined) {
return undefined;
}
if(age < 0){
if (age < 0) {
return new FixedUiElement("Cache was expired")
}
return new FixedUiElement("Loaded data is from the cache and is "+Utils.toHumanTime(age)+" old")
return new FixedUiElement("Loaded data is from the cache and is " + Utils.toHumanTime(age) + " old")
})),
new Title("Live data on OSM"),
osmLiveData,
new Combine(["The live data is shown if the zoomlevel is at least ", zoomLevel, ". The current zoom level is ", new VariableUiElement(osmLiveData.location.map(l => ""+l.zoom))]).SetClass("flex"),
new Combine(["The live data is shown if the zoomlevel is at least ", zoomLevel, ". The current zoom level is ", new VariableUiElement(osmLiveData.location.map(l => "" + l.zoom))]).SetClass("flex"),
new Title("Nearby features"),
new Combine([ "The following map shows features to import which have an OSM-feature within ", nearbyCutoff, "meter"]).SetClass("flex"),
new Combine(["The following map shows features to import which have an OSM-feature within ", nearbyCutoff, "meter"]).SetClass("flex"),
new FixedUiElement("The red elements on the following map will <b>not</b> be imported!").SetClass("alert"),
"Set the range to 0 or 1 if you want to import them all",
matchedFeaturesMap]).SetClass("flex flex-col")
super([
new Title("Comparison with existing data"),
new VariableUiElement(overpassStatus.map(d => {
@ -230,16 +231,16 @@ export default class ConflationChecker extends Combine implements FlowStep<{feat
if (d["error"] !== undefined) {
return new FixedUiElement("Could not load latest data from overpass: " + d["error"]).SetClass("alert")
}
if(d === "running"){
if (d === "running") {
return new Loading("Querying overpass...")
}
if(d === "cached"){
if (d === "cached") {
return conflationMaps
}
if(d === "success"){
if (d === "success") {
return conflationMaps
}
return new FixedUiElement("Unexpected state "+d).SetClass("alert")
return new FixedUiElement("Unexpected state " + d).SetClass("alert")
}))
])

View file

@ -23,8 +23,8 @@ export class CreateNotes extends Combine {
delete f.properties["source"]
delete f.properties["src"]
let extraNote = ""
if(f.properties["note"]){
extraNote = f.properties["note"]+"\n"
if (f.properties["note"]) {
extraNote = f.properties["note"] + "\n"
delete f.properties["note"]
}

View file

@ -101,7 +101,7 @@ export class FlowPanel<T> extends Toggle {
// Startup the flow
elements = [
initial,
new Combine([
backbutton,
new Toggle(

View file

@ -27,7 +27,7 @@ export default class ImportHelperGui extends LeftIndex {
constructor() {
const state = new UserRelatedState(undefined)
const {flow, furthestStep, titles} =
const {flow, furthestStep, titles} =
FlowPanelFactory
.start("Introduction", new Introdution())
.then("Login", _ => new LoginToImport(state))
@ -37,28 +37,28 @@ export default class ImportHelperGui extends LeftIndex {
.then("Compare with open notes", v => new CompareToAlreadyExistingNotes(state, v))
.then("Compare with existing data", v => new ConflationChecker(state, v))
.then("License and community check", v => new ConfirmProcess(v))
.then("Metadata", (v:{features:any[], layer: LayerConfig}) => new AskMetadata(v))
.then("Metadata", (v: { features: any[], layer: LayerConfig }) => new AskMetadata(v))
.finish("Note creation", v => new CreateNotes(state, v));
const toc = new List(
titles.map((title, i) => new VariableUiElement(furthestStep.map(currentStep => {
if(i > currentStep){
if (i > currentStep) {
return new Combine([title]).SetClass("subtle");
}
if(i == currentStep){
if (i == currentStep) {
return new Combine([title]).SetClass("font-bold");
}
if(i < currentStep){
if (i < currentStep) {
return title
}
})))
, true)
const leftContents: BaseUIElement[] = [
new SubtleButton(undefined,"Inspect your preview imports", {
url:"import_viewer.html"
new SubtleButton(undefined, "Inspect your preview imports", {
url: "import_viewer.html"
}),
toc,
new Toggle(new FixedUiElement("Testmode - won't actually import notes").SetClass("alert"), undefined, state.featureSwitchIsTesting),

View file

@ -7,7 +7,7 @@ export class ImportUtils {
if (osmData?.features === undefined) {
return undefined
}
if(osmData.features.length === 0){
if (osmData.features.length === 0) {
return {noNearby: toPartitionFeatureCollection.features, hasNearby: []}
}
const maxDist = cutoffDistanceInMeters.data

View file

@ -7,14 +7,14 @@ import Title from "../Base/Title";
export default class Introdution extends Combine implements FlowStep<void> {
readonly IsValid: UIEventSource<boolean> = new UIEventSource<boolean>(true);
readonly Value: UIEventSource<void> = new UIEventSource<void>(undefined);
constructor() {
super([
new Title( Translations.t.importHelper.title),
new Title(Translations.t.importHelper.title),
Translations.t.importHelper.description,
Translations.t.importHelper.importFormat,
]);
this.SetClass("flex flex-col")
}
}

View file

@ -26,26 +26,26 @@ import Title from "../Base/Title";
import CheckBoxes from "../Input/Checkboxes";
class PreviewPanel extends ScrollableFullScreen {
constructor(tags, layer) {
super(
_ => new FixedUiElement("Element to import"),
_ => new Combine(["The tags are:",
_ => new Combine(["The tags are:",
new AllTagsPanel(tags)
]).SetClass("flex flex-col"),
"element"
);
}
}
/**
* Shows the data to import on a map, asks for the correct layer to be selected
*/
export class MapPreview extends Combine implements FlowStep<{ bbox: BBox, layer: LayerConfig, geojson: any }>{
export class MapPreview extends Combine implements FlowStep<{ bbox: BBox, layer: LayerConfig, geojson: any }> {
public readonly IsValid: UIEventSource<boolean>;
public readonly Value: UIEventSource<{ bbox: BBox, layer: LayerConfig, geojson: any }>
constructor(
state: UserRelatedState,
geojson: { features: { properties: any, geometry: { coordinates: [number, number] } }[] }) {
@ -115,10 +115,10 @@ export class MapPreview extends Combine implements FlowStep<{ bbox: BBox, layer:
layers: new UIEventSource<FilteredLayer[]>(AllKnownLayouts.AllPublicLayers()
.filter(l => l.source.geojsonSource === undefined)
.map(l => ({
layerDef: l,
isDisplayed: new UIEventSource<boolean>(true),
appliedFilters: new UIEventSource<Map<string, FilterState>>(undefined)
}))),
layerDef: l,
isDisplayed: new UIEventSource<boolean>(true),
appliedFilters: new UIEventSource<Map<string, FilterState>>(undefined)
}))),
zoomToFeatures: true,
features: new StaticFeatureSource(matching, false),
leafletMap: map.leafletMap,
@ -126,8 +126,8 @@ export class MapPreview extends Combine implements FlowStep<{ bbox: BBox, layer:
})
var bbox = matching.map(feats => BBox.bboxAroundAll(feats.map(f => new BBox([f.geometry.coordinates]))))
const mismatchIndicator = new VariableUiElement(matching.map(matching => {
const mismatchIndicator = new VariableUiElement(matching.map(matching => {
if (matching === undefined) {
return undefined
}
@ -138,14 +138,14 @@ export class MapPreview extends Combine implements FlowStep<{ bbox: BBox, layer:
const obligatory = layerPicker.GetValue().data?.source?.osmTags?.asHumanString(false, false, {});
return t.mismatch.Subs({count: diff, tags: obligatory}).SetClass("alert")
}))
const confirm = new CheckBoxes([t.confirm]);
super([
new Title(t.title, 1),
layerPicker,
new Toggle(t.autodetected.SetClass("thank"), undefined, autodetected),
mismatchIndicator ,
mismatchIndicator,
map,
confirm
]);
@ -156,17 +156,17 @@ export class MapPreview extends Combine implements FlowStep<{ bbox: BBox, layer:
geojson,
layer: layerPicker.GetValue().data
}), [layerPicker.GetValue()])
this.IsValid = matching.map(matching => {
if (matching === undefined) {
return false
}
if(confirm.GetValue().data.length !== 1){
if (confirm.GetValue().data.length !== 1) {
return false
}
const diff = geojson.features.length - matching.length;
return diff === 0;
}, [confirm.GetValue()])
}
}

View file

@ -36,7 +36,7 @@ export class PreviewPanel extends Combine implements FlowStep<{ features: { prop
for (const key of Array.from(propertyKeys)) {
const values = Utils.NoNull(geojson.features.map(f => f.properties[key]))
console.log("There are ",values.length,"features with attribute",key, "namely",values)
console.log("There are ", values.length, "features with attribute", key, "namely", values)
const allSame = !values.some(v => v !== values[0])
let countSummary: BaseUIElement
if (values.length === n) {

View file

@ -3,13 +3,12 @@ import {UIEventSource} from "../../Logic/UIEventSource";
import Translations from "../i18n/Translations";
import {SubtleButton} from "../Base/SubtleButton";
import {VariableUiElement} from "../Base/VariableUIElement";
import {FixedUiElement} from "../Base/FixedUiElement";
import Title from "../Base/Title";
import InputElementMap from "../Input/InputElementMap";
import BaseUIElement from "../BaseUIElement";
import FileSelectorButton from "../Input/FileSelectorButton";
import {FlowStep} from "./FlowStep";
import { parse } from "papaparse";
import {parse} from "papaparse";
class FileSelector extends InputElementMap<FileList, { name: string, contents: Promise<string> }> {
constructor(label: BaseUIElement) {
@ -76,7 +75,7 @@ export class RequestFile extends Combine implements FlowStep<any> {
} catch (e) {
// Loading as CSV
var lines : string[][] = <any> parse(src).data;
var lines: string[][] = <any>parse(src).data;
const header = lines[0]
lines.splice(0, 1)
if (header.indexOf("lat") < 0 || header.indexOf("lon") < 0) {
@ -84,26 +83,26 @@ export class RequestFile extends Combine implements FlowStep<any> {
}
if (header.some(h => h.trim() == "")) {
return {error:t.errNoName}
return {error: t.errNoName}
}
if (new Set(header).size !== header.length) {
return {error:t.errDuplicate}
return {error: t.errDuplicate}
}
const features = []
for (let i = 0; i < lines.length; i++) {
const attrs = lines[i];
if(attrs.length == 0 || (attrs.length == 1 && attrs[0] == "")){
if (attrs.length == 0 || (attrs.length == 1 && attrs[0] == "")) {
// empty line
continue
}
const properties = {}
for (let i = 0; i < header.length; i++) {
const v = attrs[i]
if(v === undefined || v === ""){
const v = attrs[i]
if (v === undefined || v === "") {
continue
}
properties[header[i]] = v;