Refactoring: refactoring of all Conversions

This commit is contained in:
Pieter Vander Vennet 2023-10-11 04:16:52 +02:00
parent 4e8dfc0026
commit f2863cdf17
38 changed files with 1177 additions and 1269 deletions

View file

@ -0,0 +1,41 @@
<script lang="ts">
import { IconConfig } from "../../Models/ThemeConfig/PointRenderingConfig";
import { Store } from "../../Logic/UIEventSource";
import Pin from "../../assets/svg/Pin.svelte";
import Square from "../../assets/svg/Square.svelte";
import Circle from "../../assets/svg/Circle.svelte";
import Checkmark from "../../assets/svg/Checkmark.svelte";
import Clock from "../../assets/svg/Clock.svelte";
import Close from "../../assets/svg/Close.svelte";
import Crosshair from "../../assets/svg/Crosshair.svelte";
import Help from "../../assets/svg/Help.svelte";
import Home from "../../assets/svg/Home.svelte";
import Invalid from "../../assets/svg/Invalid.svelte";
import Location from "../../assets/svg/Location.svelte";
import Location_empty from "../../assets/svg/Location_empty.svelte";
import Location_locked from "../../assets/svg/Location_locked.svelte";
import Note from "../../assets/svg/Note.svelte";
import Resolved from "../../assets/svg/Resolved.svelte";
import Ring from "../../assets/svg/Ring.svelte";
import Scissors from "../../assets/svg/Scissors.svelte";
import Teardrop from "../../assets/svg/Teardrop.svelte";
import Teardrop_with_hole_green from "../../assets/svg/Teardrop_with_hole_green.svelte";
import Triangle from "../../assets/svg/Triangle.svelte";
import Icon from "./Icon.svelte";
/**
* Renders a single icon.
*
* Icons -placed on top of each other- form a 'Marker' together
*/
export let icon: IconConfig;
export let tags: Store<Record<string, string>>;
let iconItem = icon.icon?.GetRenderValue(tags)?.txt;
$: iconItem = icon.icon?.GetRenderValue($tags)?.txt;
let color = icon.color?.GetRenderValue(tags)?.txt ?? "#000000";
$: color = icon.color?.GetRenderValue($tags)?.txt ?? "#000000";
</script>
<Icon icon={iconItem} {color}/>

View file

@ -0,0 +1,21 @@
<script lang="ts">
import PointRenderingConfig, { IconConfig } from "../../Models/ThemeConfig/PointRenderingConfig";
import { Store } from "../../Logic/UIEventSource";
import DynamicIcon from "./DynamicIcon.svelte";
/**
* Renders a 'marker', which consists of multiple 'icons'
*/
export let config: PointRenderingConfig;
let icons: IconConfig[] = config.marker;
export let tags: Store<Record<string, string>>;
</script>
{#if config !== undefined}
<div class="relative w-full h-full">
{#each icons as icon}
<DynamicIcon {icon} {tags} />
{/each}
</div>
{/if}

View file

@ -1,6 +1,4 @@
<script lang="ts">
import { IconConfig } from "../../Models/ThemeConfig/PointRenderingConfig";
import { Store } from "../../Logic/UIEventSource";
import Pin from "../../assets/svg/Pin.svelte";
import Square from "../../assets/svg/Square.svelte";
import Circle from "../../assets/svg/Circle.svelte";
@ -27,60 +25,56 @@
*
* Icons -placed on top of each other- form a 'Marker' together
*/
export let icon: IconConfig;
export let tags: Store<Record<string, string>>;
let iconItem = icon.icon?.GetRenderValue(tags)?.txt;
$: iconItem = icon.icon?.GetRenderValue($tags)?.txt;
let color = icon.color?.GetRenderValue(tags)?.txt ?? "#000000";
$: color = icon.color?.GetRenderValue($tags)?.txt ?? "#000000";
export let icon: string | undefined;
export let color: string | undefined;
</script>
{#if iconItem}
{#if icon}
<div class="absolute top-0 left-0 w-full h-full">
{#if iconItem === "pin"}
{#if icon === "pin"}
<Pin {color} />
{:else if iconItem === "square"}
{:else if icon === "square"}
<Square {color} />
{:else if iconItem === "circle"}
{:else if icon === "circle"}
<Circle {color} />
{:else if iconItem === "checkmark"}
{:else if icon === "checkmark"}
<Checkmark {color} />
{:else if iconItem === "clock"}
{:else if icon === "clock"}
<Clock {color} />
{:else if iconItem === "close"}
{:else if icon === "close"}
<Close {color} />
{:else if iconItem === "crosshair"}
{:else if icon === "crosshair"}
<Crosshair {color} />
{:else if iconItem === "help"}
{:else if icon === "help"}
<Help {color} />
{:else if iconItem === "home"}
{:else if icon === "home"}
<Home {color} />
{:else if iconItem === "invalid"}
{:else if icon === "invalid"}
<Invalid {color} />
{:else if iconItem === "location"}
{:else if icon === "location"}
<Location {color} />
{:else if iconItem === "location_empty"}
{:else if icon === "location_empty"}
<Location_empty {color} />
{:else if iconItem === "location_locked"}
{:else if icon === "location_locked"}
<Location_locked {color} />
{:else if iconItem === "note"}
{:else if icon === "note"}
<Note {color} />
{:else if iconItem === "resolved"}
{:else if icon === "resolved"}
<Resolved {color} />
{:else if iconItem === "ring"}
{:else if icon === "ring"}
<Ring {color} />
{:else if iconItem === "scissors"}
{:else if icon === "scissors"}
<Scissors {color} />
{:else if iconItem === "teardrop"}
{:else if icon === "teardrop"}
<Teardrop {color} />
{:else if iconItem === "teardrop_with_hole_green"}
{:else if icon === "teardrop_with_hole_green"}
<Teardrop_with_hole_green {color} />
{:else if iconItem === "triangle"}
{:else if icon === "triangle"}
<Triangle {color} />
{:else}
<img class="w-full h-full" src={iconItem} />
<img class="w-full h-full" src={icon} />
{/if}
</div>
{/if}

View file

@ -1,21 +1,17 @@
<script lang="ts">
import PointRenderingConfig, { IconConfig } from "../../Models/ThemeConfig/PointRenderingConfig";
import Icon from "./Icon.svelte";
import { Store } from "../../Logic/UIEventSource";
/**
* Renders a 'marker', which consists of multiple 'icons'
*/
export let config: PointRenderingConfig;
let icons: IconConfig[] = config.marker;
export let tags: Store<Record<string, string>>;
export let icons: { icon: string, color: string }[]
</script>
{#if config !== undefined}
{#if icons !== undefined && icons.length > 0}
<div class="relative w-full h-full">
{#each icons as icon}
<Icon {icon} {tags} />
<Icon icon={icon.icon} color={icon.color} />
{/each}
</div>
{/if}

View file

@ -235,6 +235,7 @@
bind:group={selectedMapping}
name={"mappings-radio-" + config.id}
value={i}
on:keypress={e => {console.log(e) ; if(e.key === "Enter") onSave()}}
/>
</TagRenderingMappingInput>
{/each}

View file

@ -19,7 +19,7 @@
* Blacklist of regions for the general area tab
* These are regions which are handled by a different tab
*/
const regionBlacklist = ["hidden", undefined, "infobox", "tagrenderings", "maprendering", "editing", "title"];
const regionBlacklist = ["hidden", undefined, "infobox", "tagrenderings", "maprendering", "editing", "title","linerendering","pointrendering"];
const allNames = Utils.Dedup(layerSchema.map(meta => meta.hints.group));
const perRegion: Record<string, ConfigMeta[]> = {};
@ -27,7 +27,7 @@
perRegion[region] = layerSchema.filter(meta => meta.hints.group === region);
}
const baselayerRegions: string[] = ["Basic", "presets", "filters", "advanced", "expert"];
const baselayerRegions: string[] = ["Basic", "presets", "filters"];
for (const baselayerRegion of baselayerRegions) {
if (perRegion[baselayerRegion] === undefined) {
console.error("BaseLayerRegions in editLayer: no items have group '" + baselayerRegion + "\"");
@ -38,8 +38,6 @@
</script>
<h3>Editing layer {$title}</h3>
<h4>Leftover regions</h4>
{leftoverRegions.join("; ")}
<div class="m4">
<TabbedGroup tab={new UIEventSource(2)}>
<div slot="title0">General properties</div>
@ -47,9 +45,6 @@
{#each baselayerRegions as region}
<Region {state} configs={perRegion[region]} title={region} />
{/each}
{#each leftoverRegions as region}
<Region {state} configs={perRegion[region]} title={region} />
{/each}
</div>
<div slot="title1">Information panel (questions and answers)</div>
<div slot="content1">
@ -63,8 +58,14 @@
<Region configs={perRegion["linerendering"]} {state} />
<Region configs={perRegion["pointrendering"]} {state} />
</div>
<div slot="title3">Configuration file</div>
<div slot="title3">Advanced functionality</div>
<div slot="content3">
<Region configs={perRegion["advanced"]} {state} />
<Region configs={perRegion["expert"]} {state} />
</div>
<div slot="title4">Configuration file</div>
<div slot="content4">
<div>
Below, you'll find the raw configuration file in `.json`-format.
This is mostly for debugging purposes

View file

@ -65,8 +65,13 @@ console.log("For ", schema.path, "got subparts", subparts)
}
function del(value) {
values.data.splice(values.data.indexOf(value));
const index = values.data.indexOf(value)
console.log("Deleting",value, index)
values.data.splice(index, 1);
const store = <UIEventSource<[]>>state.getStoreFor(path);
store.data.splice(index, 1)
values.ping();
store.ping()
}
</script>

View file

@ -96,13 +96,13 @@
err = path.join(".") + " " + e
}
let startValue = state.getCurrentValueFor(path)
if (typeof startValue !== "string") {
startValue = JSON.stringify(startValue)
}
const tags = new UIEventSource<Record<string, string>>({value: startValue ?? ""})
try {
onDestroy(state.register(path, tags.map(tgs => {
const v = tgs["value"];
if(typeof v !== "string"){
return v
}
if (schema.type === "boolan") {
return v === "true" || v === "yes" || v === "1"
}
@ -135,7 +135,6 @@
<span class="alert">{err}</span>
{:else}
<div class="w-full flex flex-col">
<span class="subtle">{path.join(".")}</span>
<TagRenderingEditable {config} selectedElement={undefined} showQuestionIfUnknown={true} {state} {tags}/>
</div>
{/if}

View file

@ -214,5 +214,4 @@
path={[...subpath, (subschema?.path?.at(-1) ?? "???")]}></SchemaBasedInput>
{/each}
{/if}
{chosenOption}
</div>

View file

@ -0,0 +1,38 @@
import { Utils } from "../../Utils"
import Constants from "../../Models/Constants"
import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson"
export default class StudioServer {
private _url: string
constructor(url: string) {
this._url = url
}
public async fetchLayerOverview(): Promise<Set<string>> {
const { allFiles } = <{ allFiles: string[] }>(
await Utils.downloadJson(this._url + "/overview")
)
const layers = allFiles
.filter((f) => f.startsWith("layers/"))
.map((l) => l.substring(l.lastIndexOf("/") + 1, l.length - ".json".length))
.filter((layerId) => Constants.priviliged_layers.indexOf(<any>layerId) < 0)
return new Set<string>(layers)
}
async fetchLayer(layerId: string, checkNew: boolean = false): Promise<LayerConfigJson> {
try {
return await Utils.downloadJson(
this._url +
"/layers/" +
layerId +
"/" +
layerId +
".json" +
(checkNew ? ".new.json" : "")
)
} catch (e) {
return undefined
}
}
}

View file

@ -2,35 +2,32 @@
import NextButton from "./Base/NextButton.svelte";
import { Utils } from "../Utils";
import { UIEventSource } from "../Logic/UIEventSource";
import Constants from "../Models/Constants";
import ValidatedInput from "./InputElement/ValidatedInput.svelte";
import EditLayerState from "./Studio/EditLayerState";
import EditLayer from "./Studio/EditLayer.svelte";
import Loading from "../assets/svg/Loading.svelte";
import Marker from "./Map/Marker.svelte";
import { AllSharedLayers } from "../Customizations/AllSharedLayers";
import StudioServer from "./Studio/StudioServer";
import LoginToggle from "./Base/LoginToggle.svelte";
import { OsmConnection } from "../Logic/Osm/OsmConnection";
import { QueryParameters } from "../Logic/Web/QueryParameters";
export let studioUrl = "http://127.0.0.1:1235";
let overview = UIEventSource.FromPromise<{ allFiles: string[] }>(Utils.downloadJson(studioUrl + "/overview"));
let layers = overview.map(overview => {
if (!overview) {
return [];
}
return overview.allFiles.filter(f => f.startsWith("layers/")
).map(l => l.substring(l.lastIndexOf("/") + 1, l.length - ".json".length))
.filter(layerId => Constants.priviliged_layers.indexOf(layerId) < 0);
});
const studio = new StudioServer(studioUrl);
let layers = UIEventSource.FromPromise(studio.fetchLayerOverview());
let state: undefined | "edit_layer" | "new_layer" | "edit_theme" | "new_theme" | "editing_layer" | "loading" = undefined;
let initialLayerConfig: undefined;
let initialLayerConfig: { id: string };
let newLayerId = new UIEventSource<string>("");
let layerIdFeedback = new UIEventSource<string>(undefined);
newLayerId.addCallbackD(layerId => {
if (layerId === "") {
return;
}
if (layers.data.indexOf(layerId) >= 0) {
if (layers.data.has(layerId)) {
layerIdFeedback.setData("This id is already used");
}
}, [layers]);
@ -38,7 +35,28 @@
let editLayerState = new EditLayerState();
function fetchIconDescription(layerId): any {
const icon = AllSharedLayers.getSharedLayersConfigs().get(layerId)?._layerIcon;
console.log(icon);
return icon;
}
let osmConnection = new OsmConnection( new OsmConnection({
oauth_token: QueryParameters.GetQueryParameter(
"oauth_token",
undefined,
"Used to complete the login"
),
}))
</script>
<LoginToggle state={{osmConnection}}>
<div slot="not-logged-in" >
<NextButton clss="primary">
Please log in to use MapComplete Studio
</NextButton>
</div>
{#if state === undefined}
<h1>MapComplete Studio</h1>
<div class="w-full flex flex-col">
@ -58,13 +76,16 @@
</div>
{:else if state === "edit_layer"}
<div class="flex flex-wrap">
{#each $layers as layerId}
{#each Array.from($layers) as layerId}
<NextButton clss="small" on:click={async () => {
console.log("Editing layer",layerId)
state = "loading"
initialLayerConfig = await Utils.downloadJson(studioUrl+"/layers/"+layerId+"/"+layerId+".json")
initialLayerConfig = await studio.fetchLayer(layerId)
state = "editing_layer"
}}>
<div class="w-4 h-4 mr-1">
<Marker icons={fetchIconDescription(layerId)} />
</div>
{layerId}
</NextButton>
{/each}
@ -76,12 +97,22 @@
{$layerIdFeedback}
</div>
{:else }
<NextButton on:click={() => {initialLayerConfig = ({id: newLayerId.data}); state = "editing_layer"}}>
<NextButton on:click={async () => {
state = "loading"
const id = newLayerId.data
const createdBy = osmConnection.userDetails.data.name
const loaded = await studio.fetchLayer(id, true)
initialLayerConfig = loaded ?? {id, credits: createdBy};
state = "editing_layer"}}>
Create this layer
</NextButton>
{/if}
{:else if state === "loading"}
<Loading />
<div class="w-8 h-8">
<Loading />
</div>
{:else if state === "editing_layer"}
<EditLayer {initialLayerConfig} />
{/if}
</LoginToggle>