Merge develop

This commit is contained in:
Pieter Vander Vennet 2023-12-03 04:44:59 +01:00
commit d959b6b40b
290 changed files with 37178 additions and 2200 deletions

View file

@ -137,7 +137,6 @@ export default class GeoLocationHandler {
}
}
console.trace("Moving the map to the GPS-location")
mapLocation.setData({
lon: newLocation.longitude,
lat: newLocation.latitude,
@ -152,7 +151,6 @@ export default class GeoLocationHandler {
private CopyGeolocationIntoMapstate() {
const features: UIEventSource<Feature[]> = new UIEventSource<Feature[]>([])
this.currentUserLocation = new StaticFeatureSource(features)
const keysToCopy = ["speed", "accuracy", "altitude", "altitudeAccuracy", "heading"]
let i = 0
this.geolocationState.currentGPSLocation.addCallbackAndRun((location) => {
if (location === undefined) {
@ -163,18 +161,15 @@ export default class GeoLocationHandler {
id: "gps-" + i,
"user:location": "yes",
date: new Date().toISOString(),
// GeolocationObject behaves really weird when indexing, so copying it one by one is the most stable
accuracy: location.accuracy,
speed: location.speed,
altitude: location.altitude,
altitudeAccuracy: location.altitudeAccuracy,
heading: location.heading,
}
i++
for (const k in keysToCopy) {
// For some weird reason, the 'Object.keys' method doesn't work for the 'location: GeolocationCoordinates'-object and will thus not copy all the properties when using {...location}
// As such, they are copied here
if (location[k]) {
properties[k] = location[k]
}
}
properties["_all"] = JSON.stringify(location)
const feature = <Feature>{
type: "Feature",
properties,
@ -183,7 +178,6 @@ export default class GeoLocationHandler {
coordinates: [location.longitude, location.latitude],
},
}
features.setData([feature])
})
}

View file

@ -48,6 +48,7 @@ export class PreferredRasterLayerSelector {
this._preferredBackgroundLayer.addCallbackD((_) => self.updateLayer())
this._availableLayers.addCallbackD((_) => self.updateLayer())
self.updateLayer()
}
/**
@ -63,6 +64,12 @@ export class PreferredRasterLayerSelector {
const foundLayer = isCategory
? available.find((l) => l.properties.category === targetLayerId)
: available.find((l) => l.properties.id === targetLayerId)
console.debug("Updating background layer to", foundLayer?.id, {
targetLayerId,
queryParam: this._queryParameter?.data,
preferred: this._preferredBackgroundLayer?.data,
isCategory,
})
if (foundLayer) {
this._rasterLayerSetting.setData(foundLayer)
return true

View file

@ -31,11 +31,12 @@ export default class GenericImageProvider extends ImageProvider {
key: key,
url: value,
provider: this,
id: value
}),
]
}
SourceIcon(backlinkSource?: string) {
SourceIcon() {
return undefined
}

View file

@ -6,13 +6,14 @@ import { Utils } from "../../Utils"
export interface ProvidedImage {
url: string
key: string
provider: ImageProvider
provider: ImageProvider,
id: string
}
export default abstract class ImageProvider {
public abstract readonly defaultKeyPrefixes: string[]
public abstract SourceIcon(backlinkSource?: string): BaseUIElement
public abstract SourceIcon(id?: string, location?: {lon: number, lat: number}): BaseUIElement
/**
* Given a properies object, maps it onto _all_ the available pictures for this imageProvider
@ -28,7 +29,7 @@ export default abstract class ImageProvider {
throw "No `defaultKeyPrefixes` defined by this image provider"
}
const relevantUrls = new UIEventSource<
{ url: string; key: string; provider: ImageProvider }[]
{ id: string, url: string; key: string; provider: ImageProvider }[]
>([])
const seenValues = new Set<string>()
allTags.addCallbackAndRunD((tags) => {
@ -67,4 +68,10 @@ export default abstract class ImageProvider {
public abstract DownloadAttribution(url: string): Promise<LicenseInfo>
public abstract apiUrls(): string[]
public backlink(): string | undefined {
return undefined
}
}

View file

@ -66,6 +66,7 @@ export class Imgur extends ImageProvider implements ImageUploader {
url: value,
key: key,
provider: this,
id: value
}),
]
}

View file

@ -4,6 +4,7 @@ import Svg from "../../Svg"
import { Utils } from "../../Utils"
import { LicenseInfo } from "./LicenseInfo"
import Constants from "../../Models/Constants"
import Link from "../../UI/Base/Link"
export class Mapillary extends ImageProvider {
public static readonly singleton = new Mapillary()
@ -17,10 +18,6 @@ export class Mapillary extends ImageProvider {
]
defaultKeyPrefixes = ["mapillary", "image"]
apiUrls(): string[] {
return ["https://mapillary.com", "https://www.mapillary.com", "https://graph.mapillary.com"]
}
/**
* Indicates that this is the same URL
* Ignores 'stp' parameter
@ -57,6 +54,22 @@ export class Mapillary extends ImageProvider {
return false
}
static createLink(location: {
lon: number,
lat: number
} = undefined, zoom: number = 17, pKey?: string) {
const params = {
focus: pKey === undefined ? "map" : "photo",
lat: location.lat,
lng: location.lon,
z: location === undefined ? undefined : Math.max((zoom ?? 2) - 1, 1),
pKey,
}
const baselink = `https://www.mapillary.com/app/?`
const paramsStr = Utils.NoNull(Object.keys(params).map(k => params[k] === undefined ? undefined : k + "=" + params[k]))
return baselink + paramsStr.join("&")
}
/**
* Returns the correct key for API v4.0
*/
@ -80,8 +93,19 @@ export class Mapillary extends ImageProvider {
return undefined
}
SourceIcon(backlinkSource?: string): BaseUIElement {
return Svg.mapillary_svg()
apiUrls(): string[] {
return ["https://mapillary.com", "https://www.mapillary.com", "https://graph.mapillary.com"]
}
SourceIcon(id: string, location?: {
lon: number,
lat: number
}): BaseUIElement {
const icon = Svg.mapillary_svg()
if (!id) {
return icon
}
return new Link(icon, Mapillary.createLink(location, 16, "" + id), true)
}
async ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]> {
@ -111,6 +135,7 @@ export class Mapillary extends ImageProvider {
const response = await Utils.downloadJsonCached(metadataUrl, 60 * 60)
const url = <string>response["thumb_1024_url"]
return {
id: "" + mapillaryId,
url: url,
provider: this,
key: key,

View file

@ -15,7 +15,7 @@ export class WikidataImageProvider extends ImageProvider {
super()
}
public SourceIcon(_?: string): BaseUIElement {
public SourceIcon(): BaseUIElement {
return Svg.wikidata_svg()
}

View file

@ -1,7 +1,6 @@
import ImageProvider, { ProvidedImage } from "./ImageProvider"
import BaseUIElement from "../../UI/BaseUIElement"
import Svg from "../../Svg"
import Link from "../../UI/Base/Link"
import { Utils } from "../../Utils"
import { LicenseInfo } from "./LicenseInfo"
import Wikimedia from "../Web/Wikimedia"
@ -70,17 +69,8 @@ export class WikimediaImageProvider extends ImageProvider {
return WikimediaImageProvider.apiUrls
}
SourceIcon(backlink: string): BaseUIElement {
const img = Svg.wikimedia_commons_white_svg().SetStyle("width:2em;height: 2em")
if (backlink === undefined) {
return img
}
return new Link(
Svg.wikimedia_commons_white_svg(),
`https://commons.wikimedia.org/wiki/${backlink}`,
true
)
SourceIcon(): BaseUIElement {
return Svg.wikimedia_commons_white_svg().SetStyle("width:2em;height: 2em")
}
public PrepUrl(value: string): ProvidedImage {
@ -173,6 +163,6 @@ export class WikimediaImageProvider extends ImageProvider {
if (!image.startsWith("File:")) {
image = "File:" + image
}
return { url: WikimediaImageProvider.PrepareUrl(image), key: undefined, provider: this }
return { url: WikimediaImageProvider.PrepareUrl(image), key: undefined, provider: this , id: image}
}
}

View file

@ -31,7 +31,7 @@ export class Stores {
* @param promise
* @constructor
*/
public static FromPromise<T>(promise: Promise<T>): Store<T> {
public static FromPromise<T>(promise: Promise<T>): Store<T | undefined> {
const src = new UIEventSource<T>(undefined)
promise?.then((d) => src.setData(d))
promise?.catch((err) => console.warn("Promise failed:", err))
@ -97,7 +97,7 @@ export abstract class Store<T> implements Readable<T> {
abstract map<J>(f: (t: T) => J): Store<J>
abstract map<J>(f: (t: T) => J, extraStoresToWatch: Store<any>[]): Store<J>
public mapD<J>(f: (t: T) => J, extraStoresToWatch?: Store<any>[]): Store<J> {
public mapD<J>(f: (t: Exclude<T, undefined | null>) => J, extraStoresToWatch?: Store<any>[]): Store<J> {
return this.map((t) => {
if (t === undefined) {
return undefined
@ -105,7 +105,7 @@ export abstract class Store<T> implements Readable<T> {
if (t === null) {
return null
}
return f(t)
return f(<Exclude<T, undefined | null>> t)
}, extraStoresToWatch)
}
@ -603,7 +603,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
*/
public static FromPromiseWithErr<T>(
promise: Promise<T>
): UIEventSource<{ success: T } | { error: any }> {
): UIEventSource<{ success: T } | { error: any } | undefined> {
const src = new UIEventSource<{ success: T } | { error: any }>(undefined)
promise?.then((d) => src.setData({ success: d }))
promise?.catch((err) => src.setData({ error: err }))
@ -771,18 +771,21 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
* Monoidal map which results in a read-only store. 'undefined' is passed 'as is'
* Given a function 'f', will construct a new UIEventSource where the contents will always be "f(this.data)'
*/
public mapD<J>(f: (t: T) => J, extraSources: Store<any>[] = []): Store<J | undefined> {
public mapD<J>(f: (t: Exclude<T, undefined | null>) => J, extraSources: Store<any>[] = []): Store<J | undefined> {
return new MappedStore(
this,
(t) => {
if (t === undefined) {
return undefined
}
return f(t)
if (t === null) {
return null
}
return f(<Exclude<T, undefined | null>> t)
},
extraSources,
this._callbacks,
this.data === undefined ? undefined : f(this.data)
(this.data === undefined || this.data === null) ?(<undefined | null> this.data) : f(<any> this.data)
)
}

View file

@ -40,15 +40,26 @@ export interface P4CPicture {
export default class NearbyImagesSearch {
public static readonly services = ["mapillary", "flickr", "kartaview", "wikicommons"] as const
public static readonly apiUrls = ["https://api.flickr.com"]
private readonly individualStores: Store<{ images: P4CPicture[]; beforeFilter: number }>[]
private readonly individualStores: Store<{ images: P4CPicture[]; beforeFilter: number } | undefined>[]
private readonly _store: UIEventSource<P4CPicture[]> = new UIEventSource<P4CPicture[]>([])
public readonly store: Store<P4CPicture[]> = this._store
public readonly allDone: Store<boolean>
private readonly _options: NearbyImageOptions
constructor(options: NearbyImageOptions, features: IndexedFeatureSource) {
this.individualStores = NearbyImagesSearch.services.map((s) =>
NearbyImagesSearch.buildPictureFetcher(options, s)
)
const allDone = new UIEventSource(false)
this.allDone = allDone
const self = this
function updateAllDone(){
const stillRunning = self.individualStores.some(store => store.data === undefined)
allDone.setData(!stillRunning)
}
self.individualStores.forEach(s => s.addCallback(_ => updateAllDone()))
this._options = options
if (features !== undefined) {
const osmImages = new ImagesInLoadedDataFetcher(features).fetchAround({
@ -93,13 +104,17 @@ export default class NearbyImagesSearch {
private static buildPictureFetcher(
options: NearbyImageOptions,
fetcher: P4CService
): Store<{ images: P4CPicture[]; beforeFilter: number }> {
const p4cStore = Stores.FromPromise<P4CPicture[]>(
): Store<{ images: P4CPicture[]; beforeFilter: number } | null | undefined> {
const p4cStore = Stores.FromPromiseWithErr<P4CPicture[]>(
NearbyImagesSearch.fetchImages(options, fetcher)
)
const searchRadius = options.searchRadius ?? 100
return p4cStore.map(
(images) => {
return p4cStore.mapD(
(imagesState) => {
if(imagesState["error"]){
return null
}
let images = imagesState["success"]
if (images === undefined) {
return undefined
}

View file

@ -168,8 +168,18 @@ export class UpdateLegacyLayer extends DesugaringStep<
const pr = rendering
if (pr["icon"]) {
try {
const icon = Utils.NoEmpty(pr["icon"].split(";"))
let iconConfig = pr["icon"]
if (
Object.keys(iconConfig).length === 1 &&
iconConfig["render"] !== undefined
) {
iconConfig = iconConfig.render
}
const icon = Utils.NoEmpty(iconConfig.split(";"))
pr.marker = icon.map((i) => {
if (i.startsWith("http")) {
return { icon: i }
}
const [iconPath, color] = i.split(":")
return { icon: iconPath, color }
})
@ -243,10 +253,6 @@ class UpdateLegacyTheme extends DesugaringStep<LayoutConfigJson> {
delete oldThemeConfig.socialImage
}
if (oldThemeConfig.defaultBackgroundId === "osm") {
console.log("Removing old background in", json.id)
}
if (typeof oldThemeConfig.credits === "string") {
oldThemeConfig.credits = [oldThemeConfig.credits]
}

View file

@ -1266,6 +1266,59 @@ export class AddRatingBadge extends DesugaringStep<LayerConfigJson> {
return json
}
}
export class AutoTitleIcon extends DesugaringStep<LayerConfigJson> {
constructor() {
super(
"The auto-icon creates a (non-clickable) title icon based on a tagRendering which has icons",
["titleIcons"],
"AutoTitleIcon"
)
}
convert(json: LayerConfigJson, context: ConversionContext): LayerConfigJson {
json = { ...json }
json.titleIcons = [...json.titleIcons]
for (let i = 0; i < json.titleIcons.length; i++) {
const titleIcon = json.titleIcons[i]
if (typeof titleIcon !== "string") {
continue
}
if (!titleIcon.startsWith("auto:")) {
continue
}
const trId = titleIcon.substring("auto:".length)
const tr = <QuestionableTagRenderingConfigJson>(
json.tagRenderings.find((tr) => tr["id"] === trId)
)
if (tr === undefined) {
context.enters("titleIcons", i).err("TagRendering with id " + trId + " not found")
continue
}
const mappings: { if: TagConfigJson; then: string }[] = tr.mappings
?.filter((m) => m.icon !== undefined)
.map((m) => {
const path: string = typeof m.icon === "string" ? m.icon : m.icon.path
const img = `<img class="m-1 h-6 w-6 low-interaction rounded" src='${path}'/>`
return { if: m.if, then: img }
})
if (mappings.length === 0) {
context
.enters("titleIcons", i)
.warn(
"TagRendering with id " +
trId +
" does not have any icons, not generating an icon for this"
)
continue
}
json.titleIcons[i] = <TagRenderingConfigJson>{
id: "title_icon_auto_" + trId,
mappings,
}
}
return json
}
}
export class PrepareLayer extends Fuse<LayerConfigJson> {
constructor(state: DesugaringContext) {
@ -1294,6 +1347,7 @@ export class PrepareLayer extends Fuse<LayerConfigJson> {
new SetDefault("titleIcons", ["icons.defaults"]),
new AddRatingBadge(),
new AddFavouriteBadges(),
new AutoTitleIcon(),
new On(
"titleIcons",
(layer) =>

View file

@ -814,6 +814,12 @@ class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJson> {
)
}
if (Object.keys(json).length === 1 && typeof json["render"] === "string") {
context.warn(
`use the content directly instead of {render: ${JSON.stringify(json["render"])}}`
)
}
{
for (const key of ["question", "questionHint", "render"]) {
CheckTranslation.allowUndefined.convert(json[key], context.enter(key))

View file

@ -240,6 +240,8 @@ export interface LayerConfigJson {
* Use an empty array to hide them.
* Note that "defaults" will insert all the default titleIcons (which are added automatically)
*
* Use `auto:<tagrenderingId>` to automatically create an icon based on a tagRendering which has icons
*
* Type: icon[]
* group: infobox
*/

View file

@ -3,18 +3,15 @@ import TagRenderingConfig from "./TagRenderingConfig"
import { TagsFilter } from "../../Logic/Tags/TagsFilter"
import { TagUtils } from "../../Logic/Tags/TagUtils"
import { Utils } from "../../Utils"
import Svg from "../../Svg"
import WithContextLoader from "./WithContextLoader"
import { ImmutableStore, Store } from "../../Logic/UIEventSource"
import BaseUIElement from "../../UI/BaseUIElement"
import { FixedUiElement } from "../../UI/Base/FixedUiElement"
import Img from "../../UI/Base/Img"
import Combine from "../../UI/Base/Combine"
import { VariableUiElement } from "../../UI/Base/VariableUIElement"
import { TagRenderingConfigJson } from "./Json/TagRenderingConfigJson"
import SvelteUIElement from "../../UI/Base/SvelteUIElement"
import DynamicMarker from "../../UI/Map/DynamicMarker.svelte"
import { html } from "svelte/types/compiler/utils/namespaces"
export class IconConfig extends WithContextLoader {
public static readonly defaultIcon = new IconConfig({ icon: "pin", color: "#ff9939" })

View file

@ -27,11 +27,6 @@ export default class WithContextLoader {
`${translationContext ?? this._context}.${key}.default value`
)
}
if (Object.keys(v).length === 1 && typeof v["render"] === "string") {
throw `At ${
translationContext ?? "<unknown>"
}: use the content directly instead of {${key}: ${JSON.stringify(v)}}`
}
return new TagRenderingConfig(
<QuestionableTagRenderingConfigJson>v,

View file

@ -1,74 +1,73 @@
<script lang="ts">
import { OsmConnectionFeatureSwitches } from "../Logic/State/FeatureSwitchState";
import { OsmConnection } from "../Logic/Osm/OsmConnection";
import { QueryParameters } from "../Logic/Web/QueryParameters";
import UserRelatedState from "../Logic/State/UserRelatedState";
import LanguagePicker from "./InputElement/LanguagePicker.svelte";
import Translations from "./i18n/Translations";
import Logo from "../assets/svg/Logo.svelte";
import Tr from "./Base/Tr.svelte";
import ToSvelte from "./Base/ToSvelte.svelte";
import MoreScreen from "./BigComponents/MoreScreen";
import LoginToggle from "./Base/LoginToggle.svelte";
import Pencil from "../assets/svg/Pencil.svelte";
import Login from "../assets/svg/Login.svelte";
import Constants from "../Models/Constants";
import { OsmConnectionFeatureSwitches } from "../Logic/State/FeatureSwitchState"
import { OsmConnection } from "../Logic/Osm/OsmConnection"
import { QueryParameters } from "../Logic/Web/QueryParameters"
import UserRelatedState from "../Logic/State/UserRelatedState"
import LanguagePicker from "./InputElement/LanguagePicker.svelte"
import Translations from "./i18n/Translations"
import Logo from "../assets/svg/Logo.svelte"
import Tr from "./Base/Tr.svelte"
import ToSvelte from "./Base/ToSvelte.svelte"
import MoreScreen from "./BigComponents/MoreScreen"
import LoginToggle from "./Base/LoginToggle.svelte"
import Pencil from "../assets/svg/Pencil.svelte"
import Login from "../assets/svg/Login.svelte"
import Constants from "../Models/Constants"
const featureSwitches = new OsmConnectionFeatureSwitches();
const featureSwitches = new OsmConnectionFeatureSwitches()
const osmConnection = new OsmConnection({
fakeUser: featureSwitches.featureSwitchFakeUser.data,
oauth_token: QueryParameters.GetQueryParameter(
"oauth_token",
undefined,
"Used to complete the login"
)
});
const state = new UserRelatedState(osmConnection);
const t = Translations.t.index;
let userLanguages = osmConnection.userDetails.map(ud => ud.languages);
),
})
const state = new UserRelatedState(osmConnection)
const t = Translations.t.index
let userLanguages = osmConnection.userDetails.map((ud) => ud.languages)
</script>
<div class="flex flex-col m-4">
<div class="self-end">
<LanguagePicker assignTo={state.language} availableLanguages={t.title.SupportedLanguages()}
<div class="m-4 flex flex-col">
<LanguagePicker clss="self-end" assignTo={state.language} availableLanguages={t.title.SupportedLanguages()}
preferredLanguages={userLanguages} />
</div>
<div class="flex mt-4">
<div class="flex-none m-3">
<Logo alt="MapComplete Logo" class="w-12 h-12 sm:h-24 sm:w-24" />
<div class="mt-4 flex">
<div class="m-3 flex-none">
<Logo alt="MapComplete Logo" class="h-12 w-12 sm:h-24 sm:w-24" />
</div>
<div class="flex flex-col">
<h1 class="tracking-tight font-extrabold md:text-6xl m-0">
<h1 class="m-0 font-extrabold tracking-tight md:text-6xl">
<Tr t={t.title} />
</h1>
<Tr cls="my-4 mr-4 text-base font-semibold sm:text-lg md:mt-5 md:text-xl lg:mx-0"
t={Translations.t.index.intro} />
<Tr
cls="my-4 mr-4 text-base font-semibold sm:text-lg md:mt-5 md:text-xl lg:mx-0"
t={Translations.t.index.intro}
/>
</div>
</div>
<ToSvelte construct={new MoreScreen(state, true)} />
<LoginToggle state={state}>
<LoginToggle {state}>
<div slot="not-logged-in">
<button class="w-full" on:click={() => osmConnection.AttemptLogin()}>
<Login class="w-6 h-6 mr-2 "/>
<Login class="mr-2 h-6 w-6 " />
<Tr t={Translations.t.index.logIn} />
</button>
</div>
<a class="w-full h-fit button" href={window.location.protocol + "//" + window.location.host + "/studio.html"}>
<Pencil class="w-6 h-6 mr-2" />
<Tr t={ Translations.t.general.morescreen.createYourOwnTheme} />
<a
class="button h-fit w-full"
href={window.location.protocol + "//" + window.location.host + "/studio.html"}
>
<Pencil class="mr-2 h-6 w-6" />
<Tr t={Translations.t.general.morescreen.createYourOwnTheme} />
</a>
</LoginToggle>
<Tr cls="link-underline" t={Translations.t.general.aboutMapComplete.intro}/>
<div class="subtle self-end mb-16">
<Tr cls="link-underline" t={Translations.t.general.aboutMapComplete.intro} />
<div class="subtle mb-16 self-end">
v{Constants.vNumber}
</div>
</div>

View file

@ -5,7 +5,7 @@
*/
import { Store } from "../../Logic/UIEventSource"
import { onDestroy } from "svelte"
import Hand from "../../assets/svg/Hand.svelte";
import Hand from "../../assets/svg/Hand.svelte"
let mainElem: HTMLElement
export let hideSignal: Store<any>

View file

@ -1,31 +1,31 @@
<script lang="ts">
import { UIEventSource } from "../../Logic/UIEventSource.js";
import { UIEventSource } from "../../Logic/UIEventSource.js"
export let value: UIEventSource<any>
let i: any = value.data
let htmlElement : HTMLSelectElement
function selectAppropriateValue(){
if(!htmlElement){
return;
let htmlElement: HTMLSelectElement
function selectAppropriateValue() {
if (!htmlElement) {
return
}
const v = value.data
for (let option of htmlElement.getElementsByTagName("option")) {
if(option.value === v){
if (option.value === v) {
option.selected = true
return
}
}
}
value.addCallbackD(() => selectAppropriateValue())
$: {
if(htmlElement){
if (htmlElement) {
selectAppropriateValue()
}
}
export let cls : string = undefined
</script>
<select bind:this={htmlElement} on:change={(e) => {value.setData(e.srcElement.value)}}>
<select class={cls} bind:this={htmlElement} on:change={(e) => {value.setData(e.srcElement.value)}}>
<slot />
</select>

View file

@ -6,7 +6,7 @@
import Tr from "./Tr.svelte"
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
import { ImmutableStore, UIEventSource } from "../../Logic/UIEventSource"
import Invalid from "../../assets/svg/Invalid.svelte";
import Invalid from "../../assets/svg/Invalid.svelte"
export let state: {
osmConnection: OsmConnection

View file

@ -1,13 +1,17 @@
<script lang="ts">
import { OsmConnection } from "../../Logic/Osm/OsmConnection";
import Logout from "../../assets/svg/Logout.svelte";
import Translations from "../i18n/Translations";
import Tr from "./Tr.svelte";
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
import Logout from "../../assets/svg/Logout.svelte"
import Translations from "../i18n/Translations"
import Tr from "./Tr.svelte"
export let osmConnection: OsmConnection;
</script>
<button on:click={() => {osmConnection.LogOut()}}>
<Logout class="w-6 h-6" />
<button
on:click={() => {
state.osmConnection.LogOut()
}}
>
<Logout class="h-6 w-6" />
<Tr t={Translations.t.general.logout} />
</button>

View file

@ -1,37 +1,37 @@
<script lang="ts">
import { UIEventSource } from "../../Logic/UIEventSource";
import Translations from "../i18n/Translations";
import Tr from "./Tr.svelte";
import Josm_logo from "../../assets/svg/Josm_logo.svelte";
import Constants from "../../Models/Constants";
import type { SpecialVisualizationState } from "../SpecialVisualization";
import { UIEventSource } from "../../Logic/UIEventSource"
import Translations from "../i18n/Translations"
import Tr from "./Tr.svelte"
import Josm_logo from "../../assets/svg/Josm_logo.svelte"
import Constants from "../../Models/Constants"
import type { SpecialVisualizationState } from "../SpecialVisualization"
export let state : SpecialVisualizationState
const t = Translations.t.general.attribution;
const josmState = new UIEventSource<"OK" | string>(undefined);
export let state: SpecialVisualizationState
const t = Translations.t.general.attribution
const josmState = new UIEventSource<"OK" | string>(undefined)
// Reset after 15s
josmState.stabilized(15000).addCallbackD(() => josmState.setData(undefined));
josmState.stabilized(15000).addCallbackD(() => josmState.setData(undefined))
const showButton = state.osmConnection.userDetails.map(
(ud) => ud.loggedIn && ud.csCount >= Constants.userJourney.historyLinkVisible
);
)
function openJosm() {
const bbox = state.mapProperties. bounds.data;
const bbox = state.mapProperties.bounds.data
if (bbox === undefined) {
return;
return
}
const top = bbox.getNorth();
const bottom = bbox.getSouth();
const right = bbox.getEast();
const left = bbox.getWest();
const josmLink = `http://127.0.0.1:8111/load_and_zoom?left=${left}&right=${right}&top=${top}&bottom=${bottom}`;
const top = bbox.getNorth()
const bottom = bbox.getSouth()
const right = bbox.getEast()
const left = bbox.getWest()
const josmLink = `http://127.0.0.1:8111/load_and_zoom?left=${left}&right=${right}&top=${top}&bottom=${bottom}`
Utils.download(josmLink)
.then((answer) => josmState.setData(answer.replace(/\n/g, "").trim()))
.catch(() => josmState.setData("ERROR"));
.catch(() => josmState.setData("ERROR"))
}
</script>
{#if $showButton}
{#if $josmState === undefined}
<!-- empty -->

View file

@ -1,7 +1,7 @@
<script lang="ts">
import ToSvelte from "./ToSvelte.svelte"
import Svg from "../../Svg"
import Share from "../../assets/svg/Share.svelte";
import Share from "../../assets/svg/Share.svelte"
export let generateShareData: () => {
text: string
@ -26,6 +26,6 @@
<button on:click={share} class="secondary m-0 h-8 w-8 p-0">
<slot name="content">
<Share class="w-7 h-7 p-1"/>
<Share class="h-7 w-7 p-1" />
</slot>
</button>

View file

@ -1,7 +1,7 @@
<script lang="ts">
import Locale from "../i18n/Locale"
import LinkToWeblate from "./LinkToWeblate"
import Translate from "../../assets/svg/Translate.svelte";
import Translate from "../../assets/svg/Translate.svelte"
/**
* Shows a small icon which will open up weblate; a contributor can translate the item for 'context' there

View file

@ -1,84 +1,99 @@
<script lang="ts">
import { Store, UIEventSource } from "../../Logic/UIEventSource"
import type { SpecialVisualizationState } from "../SpecialVisualization"
import { Utils } from "../../Utils"
import Loading from "../../assets/svg/Loading.svelte"
import { Store, UIEventSource } from "../../Logic/UIEventSource";
import type { SpecialVisualizationState } from "../SpecialVisualization";
import { Utils } from "../../Utils";
import Loading from "../../assets/svg/Loading.svelte";
export let tags: Store<Record<string, string>>
export let giggityUrl: string
export let state: SpecialVisualizationState
export let tags: Store<Record<string, string>>;
export let giggityUrl: string;
export let state: SpecialVisualizationState;
let name = $tags["name"];
let events: UIEventSource<{
date: Date,
start: string,
duration: string,
room: string,
slug: string,
url: string,
title: string,
track: string,
type: string,
language: string,
abstract: string,
description: string,
persons: string,
} []> = new UIEventSource(undefined);
let name = $tags["name"]
let events: UIEventSource<
{
date: Date
start: string
duration: string
room: string
slug: string
url: string
title: string
track: string
type: string
language: string
abstract: string
description: string
persons: string
}[]
> = new UIEventSource(undefined)
async function loadXml() {
if (!name) {
console.log("Not fetching giggity events as name is", name, tags);
return;
console.log("Not fetching giggity events as name is", name, tags)
return
}
const xmlStr = await Utils.downloadAdvanced(giggityUrl);
console.log("Raw xml", xmlStr);
const parser = new DOMParser();
let doc = parser.parseFromString(xmlStr.content, "application/xml");
let days = Array.from(doc.documentElement.getElementsByTagName("day"));
let today = new Date().toISOString().split("T")[0];
const eventsToday = days.find(day => day.getAttribute("date") === today);
console.log("Events today", eventsToday);
const childs = ["date", "start", "duration", "room", "slug", "url", "title", "track", "type", "language", "abstract", "description", "persons"];
const xmlStr = await Utils.downloadAdvanced(giggityUrl)
console.log("Raw xml", xmlStr)
const parser = new DOMParser()
let doc = parser.parseFromString(xmlStr.content, "application/xml")
let days = Array.from(doc.documentElement.getElementsByTagName("day"))
let today = new Date().toISOString().split("T")[0]
const eventsToday = days.find((day) => day.getAttribute("date") === today)
console.log("Events today", eventsToday)
const childs = [
"date",
"start",
"duration",
"room",
"slug",
"url",
"title",
"track",
"type",
"language",
"abstract",
"description",
"persons",
]
const now = new Date().toISOString().split("T")[1].substring(0, 5)
let eventsList = [];
let eventsList = []
for (const eventXml of Array.from(eventsToday.getElementsByTagName("event"))) {
const event: Record<string, string> = {};
const event: Record<string, string> = {}
for (const child of childs) {
const v = Array.from(eventXml.getElementsByTagName(child)).map(xml => xml.textContent).join("; ");
event[child] = v;
const v = Array.from(eventXml.getElementsByTagName(child))
.map((xml) => xml.textContent)
.join("; ")
event[child] = v
}
if(!name.startsWith(event.room)){
if (!name.startsWith(event.room)) {
continue
}
if(now > event.start){
if (now > event.start) {
continue
}
eventsList.push(event);
eventsList.push(event)
}
events.setData(eventsList);
events.setData(eventsList)
}
loadXml();
loadXml()
</script>
{#if $events === undefined}
<Loading class="h-4">Loading giggity events from {giggityUrl}</Loading>
{:else if $events.length === 0}
{:else if $events.length === 0}
<i>No upcoming events in this room</i>
{:else}
<div>
<h2>Upcoming events</h2>
{#each $events as event}
<div class="flex flex-col m-2 border border-gray-200 border-dotted">
<div class="m-2 flex flex-col border border-dotted border-gray-200">
{#if event.url}
<h3><a href={event.url} target="_blank">{event.title}</a></h3>
{:else }
<h3>{event.title}</h3>
{/if}
{:else}
<h3>{event.title}</h3>
{/if}
<div><b>{event.start}</b></div>
<i>By {event.persons}</i>
<div>

View file

@ -1,14 +1,13 @@
<script lang="ts">
import Translations from "../i18n/Translations"
import Svg from "../../Svg"
import { Store } from "../../Logic/UIEventSource"
import Tr from "../Base/Tr.svelte"
import ToSvelte from "../Base/ToSvelte.svelte"
import Mapillary_black from "../../assets/svg/Mapillary_black.svelte";
import Translations from "../i18n/Translations"
import { Store } from "../../Logic/UIEventSource"
import Tr from "../Base/Tr.svelte"
import Mapillary_black from "../../assets/svg/Mapillary_black.svelte"
import { Mapillary } from "../../Logic/ImageProviders/Mapillary"
/*
A subtleButton which opens mapillary in a new tab at the current location
*/
/*
A subtleButton which opens mapillary in a new tab at the current location
*/
export let mapProperties: {
readonly zoom: Store<number>
@ -16,13 +15,11 @@
}
let location = mapProperties.location
let zoom = mapProperties.zoom
let mapillaryLink = `https://www.mapillary.com/app/?focus=map&lat=${$location?.lat ?? 0}&lng=${
$location?.lon ?? 0
}&z=${Math.max(($zoom ?? 2) - 1, 1)}`
let mapillaryLink = Mapillary.createLink($location, $zoom)
</script>
<a class="button flex items-center" href={mapillaryLink} target="_blank">
<Mapillary_black class="w-12 h-12 m-2 mr-4 shrink-0"/>
<Mapillary_black class="m-2 mr-4 h-12 w-12 shrink-0" />
<div class="flex flex-col">
<Tr t={Translations.t.general.attribution.openMapillary} />
<Tr cls="subtle" t={Translations.t.general.attribution.mapillaryHelp} />

View file

@ -118,7 +118,7 @@ export default class MoreScreen extends Combine {
if (search === undefined) {
return true
}
search = search.toLocaleLowerCase()
search = Utils.RemoveDiacritics(search.toLocaleLowerCase())
if (search.length > 3 && layout.id.toLowerCase().indexOf(search) >= 0) {
return true
}
@ -131,7 +131,7 @@ export default class MoreScreen extends Combine {
continue
}
const term = entity["*"] ?? entity[Locale.language.data]
if (term?.toLowerCase()?.indexOf(search) >= 0) {
if (Utils.RemoveDiacritics(term?.toLowerCase())?.indexOf(search) >= 0) {
return true
}
}

View file

@ -16,7 +16,7 @@
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
import { Utils } from "../../Utils"
import { createEventDispatcher } from "svelte"
import Move_arrows from "../../assets/svg/Move_arrows.svelte";
import Move_arrows from "../../assets/svg/Move_arrows.svelte"
/**
* An advanced location input, which has support to:
@ -126,6 +126,6 @@
maxDistanceInMeters="50"
>
<slot name="image" slot="image">
<Move_arrows class="h-full max-h-24" />
<Move_arrows class="h-full max-h-24" />
</slot>
</LocationInput>

View file

@ -38,7 +38,6 @@
<div class="flex flex-col">
<!-- Title element-->
<h3>
<TagRenderingAnswer config={layer.title} {selectedElement} {state} {tags} {layer} />
</h3>
<div

View file

@ -20,15 +20,20 @@
_metatags = tags
})
)
let knownTagRenderings = layer.tagRenderings
.filter(config => (config.condition?.matchesProperties($tags) ?? true) && (config.metacondition?.matchesProperties({ ...$tags, ..._metatags } ?? true)
&& config.IsKnown($tags)))
let knownTagRenderings = layer.tagRenderings.filter(
(config) =>
(config.condition?.matchesProperties($tags) ?? true) &&
config.metacondition?.matchesProperties({ ...$tags, ..._metatags } ?? true) &&
config.IsKnown($tags)
)
$: {
knownTagRenderings = layer.tagRenderings
.filter(config => (config.condition?.matchesProperties($tags) ?? true) && (config.metacondition?.matchesProperties({ ...$tags, ..._metatags } ?? true)
&& config.IsKnown($tags)))
knownTagRenderings = layer.tagRenderings.filter(
(config) =>
(config.condition?.matchesProperties($tags) ?? true) &&
config.metacondition?.matchesProperties({ ...$tags, ..._metatags } ?? true) &&
config.IsKnown($tags)
)
}
</script>
@ -40,15 +45,15 @@
{:else}
<div class="flex h-full flex-col gap-y-2 overflow-y-auto p-1 px-2">
{#each knownTagRenderings as config (config.id)}
<TagRenderingEditable
{tags}
{config}
{state}
{selectedElement}
{layer}
{highlightedRendering}
clss={knownTagRenderings.length === 1 ? "h-full" : "tr-length-"+knownTagRenderings.length}
/>
<TagRenderingEditable
{tags}
{config}
{state}
{selectedElement}
{layer}
{highlightedRendering}
clss={knownTagRenderings.length === 1 ? "h-full" : "tr-length-" + knownTagRenderings.length}
/>
{/each}
</div>
{/if}

View file

@ -1,16 +1,15 @@
<script lang="ts">
import type { Feature } from "geojson";
import type { SpecialVisualizationState } from "../SpecialVisualization";
import SelectedElementTitle from "./SelectedElementTitle.svelte";
import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
import TagRenderingAnswer from "../Popup/TagRendering/TagRenderingAnswer.svelte";
import type { Feature } from "geojson"
import type { SpecialVisualizationState } from "../SpecialVisualization"
import SelectedElementTitle from "./SelectedElementTitle.svelte"
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
import TagRenderingAnswer from "../Popup/TagRendering/TagRenderingAnswer.svelte"
export let state: SpecialVisualizationState;
export let state: SpecialVisualizationState
export let feature: Feature
let id = feature.properties.id
let tags = state.featureProperties.getStore(id);
let tags = state.featureProperties.getStore(id)
let layer: LayerConfig = state.layout.getMatchingLayer(tags.data)
</script>
<TagRenderingAnswer config={layer.title} selectedElement={feature} {state} {tags} {layer} />
<TagRenderingAnswer config={layer.title} selectedElement={feature} {state} {tags} {layer} />

View file

@ -87,10 +87,10 @@
{#if theme.id !== personal.id || $unlockedPersonal}
<SubtleLink href={$href} options={{ extraClasses: "w-full" }}>
<img slot="image" src={theme.icon} class="mr-2 m-1 sm:mr-4 sm:m-2 block h-11 w-11" alt="" />
<img slot="image" src={theme.icon} class="m-1 mr-2 block h-11 w-11 sm:m-2 sm:mr-4" alt="" />
<span class="flex flex-col overflow-hidden text-ellipsis">
<Tr t={title} />
{#if selected}
<span class="alert">
<Tr t={Translations.t.general.morescreen.enterToOpen} />

View file

@ -1,21 +1,21 @@
<script lang="ts">
import Translations from "../i18n/Translations";
import Tr from "../Base/Tr.svelte";
import NextButton from "../Base/NextButton.svelte";
import Geosearch from "./Geosearch.svelte";
import ThemeViewState from "../../Models/ThemeViewState";
import { UIEventSource } from "../../Logic/UIEventSource";
import { SearchIcon } from "@rgossiaux/svelte-heroicons/solid";
import { twJoin } from "tailwind-merge";
import { Utils } from "../../Utils";
import type { GeolocationPermissionState } from "../../Logic/State/GeoLocationState";
import { GeoLocationState } from "../../Logic/State/GeoLocationState";
import If from "../Base/If.svelte";
import { ExclamationTriangleIcon } from "@babeard/svelte-heroicons/mini";
import type { Readable } from "svelte/store";
import Add from "../../assets/svg/Add.svelte";
import Location_refused from "../../assets/svg/Location_refused.svelte";
import Crosshair from "../../assets/svg/Crosshair.svelte";
import Translations from "../i18n/Translations"
import Tr from "../Base/Tr.svelte"
import NextButton from "../Base/NextButton.svelte"
import Geosearch from "./Geosearch.svelte"
import ThemeViewState from "../../Models/ThemeViewState"
import { UIEventSource } from "../../Logic/UIEventSource"
import { SearchIcon } from "@rgossiaux/svelte-heroicons/solid"
import { twJoin } from "tailwind-merge"
import { Utils } from "../../Utils"
import type { GeolocationPermissionState } from "../../Logic/State/GeoLocationState"
import { GeoLocationState } from "../../Logic/State/GeoLocationState"
import If from "../Base/If.svelte"
import { ExclamationTriangleIcon } from "@babeard/svelte-heroicons/mini"
import type { Readable } from "svelte/store"
import Add from "../../assets/svg/Add.svelte"
import Location_refused from "../../assets/svg/Location_refused.svelte"
import Crosshair from "../../assets/svg/Crosshair.svelte"
/**
* The theme introduction panel
@ -71,7 +71,7 @@
<If condition={state.featureSwitches.featureSwitchGeolocation}>
{#if $currentGPSLocation !== undefined || $geopermission === "prompt"}
<button class="flex w-full items-center gap-x-2" on:click={jumpToCurrentLocation}>
<Crosshair class="w-8 h-8"/>
<Crosshair class="h-8 w-8" />
<Tr t={Translations.t.general.openTheMapAtGeolocation} />
</button>
<!-- No geolocation granted - we don't show the button -->
@ -81,17 +81,23 @@
on:click={jumpToCurrentLocation}
>
<!-- Even though disabled, when clicking we request the location again in case the contributor dismissed the location popup -->
<Crosshair class="w-8 h-8" style="animation: 3s linear 0s infinite normal none running spin;" />
<Crosshair
class="h-8 w-8"
style="animation: 3s linear 0s infinite normal none running spin;"
/>
<Tr t={Translations.t.general.waitingForGeopermission} />
</button>
{:else if $geopermission === "denied"}
<button class="disabled flex w-full items-center gap-x-2">
<Location_refused class="w-8 h-8"/>
<Location_refused class="h-8 w-8" />
<Tr t={Translations.t.general.geopermissionDenied} />
</button>
{:else}
<button class="disabled flex w-full items-center gap-x-2">
<Crosshair class="w-8 h-8" style="animation: 3s linear 0s infinite normal none running spin;" />
<Crosshair
class="h-8 w-8"
style="animation: 3s linear 0s infinite normal none running spin;"
/>
<Tr t={Translations.t.general.waitingForLocation} />
</button>
{/if}
@ -149,7 +155,7 @@
<div class="links-as-button links-w-full m-2 flex flex-col gap-y-1">
<!-- bottom buttons, a bit hidden away: switch layout -->
<a class="flex" href={Utils.HomepageLink()}>
<Add class="h-6 w-6"/>
<Add class="h-6 w-6" />
<Tr t={Translations.t.general.backToIndex} />
</a>
</div>

View file

@ -71,7 +71,6 @@
gpsLayer.isDisplayed.setData(gpsIsDisplayed)
state.userRelatedState.preferencesAsTags.data["__showTimeSensitiveIcons"] = "yes"
state.userRelatedState.preferencesAsTags.ping()
}
}
</script>

View file

@ -11,7 +11,7 @@
import Locale from "../i18n/Locale"
import { UIEventSource } from "../../Logic/UIEventSource"
import DownloadHelper from "./DownloadHelper"
import Qr from "../../Utils/Qr";
import Qr from "../../Utils/Qr"
export let templateName: string
export let state: ThemeViewState
@ -31,11 +31,11 @@
freeComponentId: "belowmap",
createImage: (key: string, width: string, height: string) => {
console.log("Creating an image for key", key)
if(key === "qr"){
if (key === "qr") {
const toShare = window.location.href.split("#")[0]
return new Qr(toShare).toImageElement(parseFloat(width), parseFloat(height))
}
return downloadHelper.createImage(key, width, height);
return downloadHelper.createImage(key, width, height)
},
textSubstitutions: <Record<string, string>>{
"layout.title": state.layout.title,
@ -62,7 +62,10 @@
extension="pdf"
helperText={t.downloadAsPdfHelper}
metaIsIncluded={false}
mainText={t.pdf.current_view_generic.Subs({orientation: template.orientation, paper_size: template.format.toUpperCase()})}
mainText={t.pdf.current_view_generic.Subs({
orientation: template.orientation,
paper_size: template.format.toUpperCase(),
})}
mimetype="application/pdf"
{state}
/>

View file

@ -5,21 +5,37 @@ import ImageProvider from "../../Logic/ImageProviders/ImageProvider"
import BaseUIElement from "../BaseUIElement"
import { Mapillary } from "../../Logic/ImageProviders/Mapillary"
import { UIEventSource } from "../../Logic/UIEventSource"
import { Feature } from "geojson"
import { GeoOperations } from "../../Logic/GeoOperations"
export class AttributedImage extends Combine {
constructor(imageInfo: { url: string; provider?: ImageProvider; date?: Date }) {
constructor(imageInfo: {
id: string,
url: string;
provider?: ImageProvider;
date?: Date
}, feature?: Feature) {
let img: BaseUIElement
img = new Img(imageInfo.url, false, {
fallbackImage:
imageInfo.provider === Mapillary.singleton ? "./assets/svg/blocked.svg" : undefined,
})
let location: {
lon: number,
lat: number
} = undefined
if (feature) {
const [lon, lat] = GeoOperations.centerpointCoordinates(feature)
location = { lon, lat }
}
let attr: BaseUIElement = undefined
if (imageInfo.provider !== undefined) {
attr = new Attribution(
UIEventSource.FromPromise(imageInfo.provider?.DownloadAttribution(imageInfo.url)),
imageInfo.provider?.SourceIcon(),
imageInfo.date
imageInfo.provider?.SourceIcon(imageInfo.id, location),
imageInfo.date,
)
}

View file

@ -28,6 +28,7 @@ export default class Attribution extends VariableUiElement {
title = new Link(title, license.informationLocation.href, true)
}
}
return new Combine([
icon
?.SetClass("block left")

View file

@ -9,19 +9,21 @@ import ImageProvider from "../../Logic/ImageProviders/ImageProvider"
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
import { Changes } from "../../Logic/Osm/Changes"
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
import { Feature } from "geojson"
export class ImageCarousel extends Toggle {
constructor(
images: Store<{ key: string; url: string; provider: ImageProvider }[]>,
images: Store<{ id:string, key: string; url: string; provider: ImageProvider }[]>,
tags: Store<any>,
state: { osmConnection?: OsmConnection; changes?: Changes; layout: LayoutConfig }
state: { osmConnection?: OsmConnection; changes?: Changes; layout: LayoutConfig },
feature: Feature
) {
const uiElements = images.map(
(imageURLS: { key: string; url: string; provider: ImageProvider }[]) => {
(imageURLS: { key: string; url: string; provider: ImageProvider, id: string }[]) => {
const uiElements: BaseUIElement[] = []
for (const url of imageURLS) {
try {
let image = new AttributedImage(url)
let image = new AttributedImage(url, feature)
if (url.key !== undefined) {
image = new Combine([

View file

@ -3,15 +3,15 @@
* Shows an 'upload'-button which will start the upload for this feature
*/
import type { SpecialVisualizationState } from "../SpecialVisualization";
import { ImmutableStore, Store } from "../../Logic/UIEventSource";
import type { OsmTags } from "../../Models/OsmFeature";
import LoginToggle from "../Base/LoginToggle.svelte";
import Translations from "../i18n/Translations";
import Tr from "../Base/Tr.svelte";
import UploadingImageCounter from "./UploadingImageCounter.svelte";
import FileSelector from "../Base/FileSelector.svelte";
import Camera_plus from "../../assets/svg/Camera_plus.svelte";
import type { SpecialVisualizationState } from "../SpecialVisualization"
import { ImmutableStore, Store } from "../../Logic/UIEventSource"
import type { OsmTags } from "../../Models/OsmFeature"
import LoginToggle from "../Base/LoginToggle.svelte"
import Translations from "../i18n/Translations"
import Tr from "../Base/Tr.svelte"
import UploadingImageCounter from "./UploadingImageCounter.svelte"
import FileSelector from "../Base/FileSelector.svelte"
import Camera_plus from "../../assets/svg/Camera_plus.svelte"
export let state: SpecialVisualizationState
@ -57,7 +57,7 @@
{#if image !== undefined}
<img src={image} />
{:else}
<Camera_plus class="block w-12 h-12 p-1 text-4xl"/>
<Camera_plus class="block h-12 w-12 p-1 text-4xl" />
{/if}
{#if labelText}
{labelText}

View file

@ -6,7 +6,7 @@
import MaplibreMap from "../../Map/MaplibreMap.svelte"
import ToSvelte from "../../Base/ToSvelte.svelte"
import Svg from "../../../Svg.js"
import Direction_stroke from "../../../assets/svg/Direction_stroke.svelte";
import Direction_stroke from "../../../assets/svg/Direction_stroke.svelte"
/**
* A visualisation to pick a direction on a map background.
@ -68,6 +68,6 @@
</div>
<div bind:this={directionElem} class="absolute top-0 left-0 h-full w-full">
<Direction_stroke/>
<Direction_stroke />
</div>
</div>

View file

@ -12,7 +12,7 @@
import * as turf from "@turf/turf"
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
import { createEventDispatcher, onDestroy } from "svelte"
import Move_arrows from "../../../assets/svg/Move_arrows.svelte";
import Move_arrows from "../../../assets/svg/Move_arrows.svelte"
/**
* A visualisation to pick a location on a map background
@ -91,7 +91,7 @@
class="pointer-events-none absolute top-0 left-0 flex h-full w-full items-center p-8 opacity-50"
>
<slot name="image">
<Move_arrows class="h-full max-h-24"/>
<Move_arrows class="h-full max-h-24" />
</slot>
</div>

View file

@ -1,45 +1,44 @@
<script lang="ts">
// Languages in the language itself
import native from "../../assets/language_native.json";
// Translated languages
import language_translations from "../../assets/language_translations.json";
// Languages in the language itself
import native from "../../assets/language_native.json"
// Translated languages
import language_translations from "../../assets/language_translations.json"
import { UIEventSource } from "../../Logic/UIEventSource";
import Locale from "../i18n/Locale";
import { LanguageIcon } from "@babeard/svelte-heroicons/solid";
import Dropdown from "../Base/Dropdown.svelte";
import { UIEventSource } from "../../Logic/UIEventSource"
import Locale from "../i18n/Locale"
import { LanguageIcon } from "@babeard/svelte-heroicons/solid"
import Dropdown from "../Base/Dropdown.svelte"
import { twMerge } from "tailwind-merge"
/**
/**
* Languages one can choose from
* Defaults to _all_ languages known by MapComplete
*/
export let availableLanguages: string[] = Object.keys(native);
export let availableLanguages: string[] = Object.keys(native)
/**
* EventStore to assign to, defaults to 'Locale.langauge'
*/
export let assignTo: UIEventSource<string> = Locale.language;
export let preferredLanguages: UIEventSource<string[]> = undefined;
let preferredFiltered: string[] = undefined;
preferredLanguages?.addCallbackAndRunD(preferredLanguages => {
let lng = navigator.language;
export let assignTo: UIEventSource<string> = Locale.language
export let preferredLanguages: UIEventSource<string[]> = undefined
let preferredFiltered: string[] = undefined
preferredLanguages?.addCallbackAndRunD((preferredLanguages) => {
let lng = navigator.language
if (lng === "en-US") {
lng = "en";
lng = "en"
}
if (preferredLanguages?.indexOf(lng) < 0) {
preferredLanguages?.push(lng);
preferredLanguages?.push(lng)
}
preferredFiltered = preferredLanguages?.filter(l => availableLanguages.indexOf(l) >= 0);
});
let current = Locale.language;
preferredFiltered = preferredLanguages?.filter((l) => availableLanguages.indexOf(l) >= 0)
})
export let clss : string = undefined
let current = Locale.language
</script>
{#if availableLanguages?.length > 1}
<form class="flex items-center">
<LanguageIcon class="h-4 w-4 mr-1" />
<Dropdown value={assignTo}>
<form class={twMerge("flex items-center max-w-full pr-4", clss)}>
<LanguageIcon class="h-4 w-4 mr-1 shrink-0" />
<Dropdown cls="max-w-full" value={assignTo}>
{#if preferredFiltered}
{#each preferredFiltered as language}
<option value={language} class="font-bold">
@ -49,18 +48,17 @@
{/if}
</option>
{/each}
<option disabled></option>
<option disabled />
{/if}
{#each availableLanguages as language}
<option value={language} class="font-bold">
{native[language] ?? ""}
{#if language !== $current}
({(language_translations[language]?.[$current] + " - " + language) ?? language})
({language_translations[language]?.[$current] + " - " + language ?? language})
{/if}
</option>
{/each}
</Dropdown>
</form>
{/if}

View file

@ -1,16 +1,18 @@
<script lang="ts">
import { IconConfig } from "../../Models/ThemeConfig/PointRenderingConfig";
import { ImmutableStore, Store } from "../../Logic/UIEventSource";
import DynamicIcon from "./DynamicIcon.svelte";
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig";
import { IconConfig } from "../../Models/ThemeConfig/PointRenderingConfig"
import { ImmutableStore, Store } from "../../Logic/UIEventSource"
import DynamicIcon from "./DynamicIcon.svelte"
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"
/**
* Renders a 'marker', which consists of multiple 'icons'
*/
export let marker: IconConfig[] = config?.marker;
export let tags: Store<Record<string, string>>
export let rotation: TagRenderingConfig = undefined;
export let tags: Store<Record<string, string>>;
let _rotation = rotation ? tags.map(tags => rotation.GetRenderValue(tags).Subs(tags).txt) : new ImmutableStore(0);
let _rotation = rotation
? tags.map((tags) => rotation.GetRenderValue(tags).Subs(tags).txt)
: new ImmutableStore(0)
</script>
{#if marker && marker}

View file

@ -12,7 +12,7 @@
import { createEventDispatcher } from "svelte"
import ToSvelte from "../Base/ToSvelte.svelte"
import Svg from "../../Svg"
import Plantnet_logo from "../../assets/svg/Plantnet_logo.svelte";
import Plantnet_logo from "../../assets/svg/Plantnet_logo.svelte"
/**
* The main entry point for the plantnet wizard
@ -143,7 +143,7 @@
</BackButton>
{/if}
<div class="low-interaction flex self-end rounded-xl p-2">
<Plantnet_logo class="w-8 h-8 p-1 mr-1 bg-white rounded-full"/>
<Plantnet_logo class="mr-1 h-8 w-8 rounded-full bg-white p-1" />
<Tr t={t.poweredByPlantnet} />
</div>
</div>

View file

@ -3,110 +3,110 @@
* This component ties together all the steps that are needed to create a new point.
* There are many subcomponents which help with that
*/
import type { SpecialVisualizationState } from "../../SpecialVisualization";
import PresetList from "./PresetList.svelte";
import type PresetConfig from "../../../Models/ThemeConfig/PresetConfig";
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
import Tr from "../../Base/Tr.svelte";
import SubtleButton from "../../Base/SubtleButton.svelte";
import Translations from "../../i18n/Translations.js";
import TagHint from "../TagHint.svelte";
import { And } from "../../../Logic/Tags/And.js";
import LoginToggle from "../../Base/LoginToggle.svelte";
import Constants from "../../../Models/Constants.js";
import FilteredLayer from "../../../Models/FilteredLayer";
import { Store, UIEventSource } from "../../../Logic/UIEventSource";
import { EyeIcon, EyeOffIcon } from "@rgossiaux/svelte-heroicons/solid";
import LoginButton from "../../Base/LoginButton.svelte";
import NewPointLocationInput from "../../BigComponents/NewPointLocationInput.svelte";
import CreateNewNodeAction from "../../../Logic/Osm/Actions/CreateNewNodeAction";
import { OsmWay } from "../../../Logic/Osm/OsmObject";
import { Tag } from "../../../Logic/Tags/Tag";
import type { WayId } from "../../../Models/OsmFeature";
import Loading from "../../Base/Loading.svelte";
import type { GlobalFilter } from "../../../Models/GlobalFilter";
import { onDestroy } from "svelte";
import NextButton from "../../Base/NextButton.svelte";
import BackButton from "../../Base/BackButton.svelte";
import ToSvelte from "../../Base/ToSvelte.svelte";
import Svg from "../../../Svg";
import OpenBackgroundSelectorButton from "../../BigComponents/OpenBackgroundSelectorButton.svelte";
import { twJoin } from "tailwind-merge";
import Confirm from "../../../assets/svg/Confirm.svelte";
import Close from "../../../assets/svg/Close.svelte";
import type { SpecialVisualizationState } from "../../SpecialVisualization"
import PresetList from "./PresetList.svelte"
import type PresetConfig from "../../../Models/ThemeConfig/PresetConfig"
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
import Tr from "../../Base/Tr.svelte"
import SubtleButton from "../../Base/SubtleButton.svelte"
import Translations from "../../i18n/Translations.js"
import TagHint from "../TagHint.svelte"
import { And } from "../../../Logic/Tags/And.js"
import LoginToggle from "../../Base/LoginToggle.svelte"
import Constants from "../../../Models/Constants.js"
import FilteredLayer from "../../../Models/FilteredLayer"
import { Store, UIEventSource } from "../../../Logic/UIEventSource"
import { EyeIcon, EyeOffIcon } from "@rgossiaux/svelte-heroicons/solid"
import LoginButton from "../../Base/LoginButton.svelte"
import NewPointLocationInput from "../../BigComponents/NewPointLocationInput.svelte"
import CreateNewNodeAction from "../../../Logic/Osm/Actions/CreateNewNodeAction"
import { OsmWay } from "../../../Logic/Osm/OsmObject"
import { Tag } from "../../../Logic/Tags/Tag"
import type { WayId } from "../../../Models/OsmFeature"
import Loading from "../../Base/Loading.svelte"
import type { GlobalFilter } from "../../../Models/GlobalFilter"
import { onDestroy } from "svelte"
import NextButton from "../../Base/NextButton.svelte"
import BackButton from "../../Base/BackButton.svelte"
import ToSvelte from "../../Base/ToSvelte.svelte"
import Svg from "../../../Svg"
import OpenBackgroundSelectorButton from "../../BigComponents/OpenBackgroundSelectorButton.svelte"
import { twJoin } from "tailwind-merge"
import Confirm from "../../../assets/svg/Confirm.svelte"
import Close from "../../../assets/svg/Close.svelte"
export let coordinate: { lon: number; lat: number };
export let state: SpecialVisualizationState;
export let coordinate: { lon: number; lat: number }
export let state: SpecialVisualizationState
let selectedPreset: {
preset: PresetConfig
layer: LayerConfig
icon: string
tags: Record<string, string>
} = undefined;
let checkedOfGlobalFilters: number = 0;
let confirmedCategory = false;
} = undefined
let checkedOfGlobalFilters: number = 0
let confirmedCategory = false
$: if (selectedPreset === undefined) {
confirmedCategory = false;
creating = false;
checkedOfGlobalFilters = 0;
confirmedCategory = false
creating = false
checkedOfGlobalFilters = 0
}
let flayer: FilteredLayer = undefined;
let layerIsDisplayed: UIEventSource<boolean> | undefined = undefined;
let layerHasFilters: Store<boolean> | undefined = undefined;
let globalFilter: UIEventSource<GlobalFilter[]> = state.layerState.globalFilters;
let _globalFilter: GlobalFilter[] = [];
let flayer: FilteredLayer = undefined
let layerIsDisplayed: UIEventSource<boolean> | undefined = undefined
let layerHasFilters: Store<boolean> | undefined = undefined
let globalFilter: UIEventSource<GlobalFilter[]> = state.layerState.globalFilters
let _globalFilter: GlobalFilter[] = []
onDestroy(
globalFilter.addCallbackAndRun((globalFilter) => {
console.log("Global filters are", globalFilter);
_globalFilter = globalFilter ?? [];
console.log("Global filters are", globalFilter)
_globalFilter = globalFilter ?? []
})
);
)
$: {
flayer = state.layerState.filteredLayers.get(selectedPreset?.layer?.id);
layerIsDisplayed = flayer?.isDisplayed;
layerHasFilters = flayer?.hasFilter;
flayer = state.layerState.filteredLayers.get(selectedPreset?.layer?.id)
layerIsDisplayed = flayer?.isDisplayed
layerHasFilters = flayer?.hasFilter
}
const t = Translations.t.general.add;
const t = Translations.t.general.add
const zoom = state.mapProperties.zoom;
const zoom = state.mapProperties.zoom
const isLoading = state.dataIsLoading;
let preciseCoordinate: UIEventSource<{ lon: number; lat: number }> = new UIEventSource(undefined);
let snappedToObject: UIEventSource<string> = new UIEventSource<string>(undefined);
const isLoading = state.dataIsLoading
let preciseCoordinate: UIEventSource<{ lon: number; lat: number }> = new UIEventSource(undefined)
let snappedToObject: UIEventSource<string> = new UIEventSource<string>(undefined)
// Small helper variable: if the map is tapped, we should let the 'Next'-button grab some attention as users have to click _that_ to continue, not the map
let preciseInputIsTapped = false;
let preciseInputIsTapped = false
let creating = false;
let creating = false
/**
* Call when the user should restart the flow by clicking on the map, e.g. because they disabled filters.
* Will delete the lastclick-location
*/
function abort() {
state.selectedElement.setData(undefined);
state.selectedElement.setData(undefined)
// When aborted, we force the contributors to place the pin _again_
// This is because there might be a nearby object that was disabled; this forces them to re-evaluate the map
state.lastClickObject.features.setData([]);
preciseInputIsTapped = false;
state.lastClickObject.features.setData([])
preciseInputIsTapped = false
}
async function confirm() {
creating = true;
const location: { lon: number; lat: number } = preciseCoordinate.data;
const snapTo: WayId | undefined = <WayId>snappedToObject.data;
creating = true
const location: { lon: number; lat: number } = preciseCoordinate.data
const snapTo: WayId | undefined = <WayId>snappedToObject.data
const tags: Tag[] = selectedPreset.preset.tags.concat(
..._globalFilter.map((f) => f?.onNewPoint?.tags ?? [])
);
console.log("Creating new point at", location, "snapped to", snapTo, "with tags", tags);
)
console.log("Creating new point at", location, "snapped to", snapTo, "with tags", tags)
let snapToWay: undefined | OsmWay = undefined;
let snapToWay: undefined | OsmWay = undefined
if (snapTo !== undefined && snapTo !== null) {
const downloaded = await state.osmObjectDownloader.DownloadObjectAsync(snapTo, 0);
const downloaded = await state.osmObjectDownloader.DownloadObjectAsync(snapTo, 0)
if (downloaded !== "deleted") {
snapToWay = downloaded;
snapToWay = downloaded
}
}
@ -114,44 +114,44 @@
theme: state.layout?.id ?? "unkown",
changeType: "create",
snapOnto: snapToWay,
reusePointWithinMeters: 1
});
await state.changes.applyAction(newElementAction);
state.newFeatures.features.ping();
reusePointWithinMeters: 1,
})
await state.changes.applyAction(newElementAction)
state.newFeatures.features.ping()
// The 'changes' should have created a new point, which added this into the 'featureProperties'
const newId = newElementAction.newElementId;
console.log("Applied pending changes, fetching store for", newId);
const tagsStore = state.featureProperties.getStore(newId);
const newId = newElementAction.newElementId
console.log("Applied pending changes, fetching store for", newId)
const tagsStore = state.featureProperties.getStore(newId)
if (!tagsStore) {
console.error("Bug: no tagsStore found for", newId);
console.error("Bug: no tagsStore found for", newId)
}
{
// Set some metainfo
const properties = tagsStore.data;
const properties = tagsStore.data
if (snapTo) {
// metatags (starting with underscore) are not uploaded, so we can safely mark this
delete properties["_referencing_ways"];
properties["_referencing_ways"] = `["${snapTo}"]`;
delete properties["_referencing_ways"]
properties["_referencing_ways"] = `["${snapTo}"]`
}
properties["_backend"] = state.osmConnection.Backend();
properties["_last_edit:timestamp"] = new Date().toISOString();
const userdetails = state.osmConnection.userDetails.data;
properties["_last_edit:contributor"] = userdetails.name;
properties["_last_edit:uid"] = "" + userdetails.uid;
tagsStore.ping();
properties["_backend"] = state.osmConnection.Backend()
properties["_last_edit:timestamp"] = new Date().toISOString()
const userdetails = state.osmConnection.userDetails.data
properties["_last_edit:contributor"] = userdetails.name
properties["_last_edit:uid"] = "" + userdetails.uid
tagsStore.ping()
}
const feature = state.indexedFeatures.featuresById.data.get(newId);
console.log("Selecting feature", feature, "and opening their popup");
abort();
state.selectedLayer.setData(selectedPreset.layer);
state.selectedElement.setData(feature);
tagsStore.ping();
const feature = state.indexedFeatures.featuresById.data.get(newId)
console.log("Selecting feature", feature, "and opening their popup")
abort()
state.selectedLayer.setData(selectedPreset.layer)
state.selectedElement.setData(feature)
tagsStore.ping()
}
function confirmSync() {
confirm()
.then((_) => console.debug("New point successfully handled"))
.catch((e) => console.error("Handling the new point went wrong due to", e));
.catch((e) => console.error("Handling the new point went wrong due to", e))
}
</script>

View file

@ -9,6 +9,7 @@
import Lazy from "../Base/Lazy"
import BaseUIElement from "../BaseUIElement"
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
import { VariableUiElement } from "../Base/VariableUIElement"
//Svelte props
export let tags: UIEventSource<any>
@ -54,13 +55,11 @@
return parts
})
let _allTags = []
onDestroy(
allTags.addCallbackAndRunD((allTags) => {
_allTags = allTags
})
const tagsTable = new VariableUiElement(
allTags.mapD((_allTags) =>
new Table(["Key", "Value"], _allTags).SetClass("zebra-table break-all")
)
)
const tagsTable = new Table(["Key", "Value"], _allTags).SetClass("zebra-table break-all")
</script>
<section>

View file

@ -15,8 +15,8 @@
import NewPointLocationInput from "../BigComponents/NewPointLocationInput.svelte"
import ToSvelte from "../Base/ToSvelte.svelte"
import Svg from "../../Svg"
import Layers from "../../assets/svg/Layers.svelte";
import AddSmall from "../../assets/svg/AddSmall.svelte";
import Layers from "../../assets/svg/Layers.svelte"
import AddSmall from "../../assets/svg/AddSmall.svelte"
export let coordinate: UIEventSource<{ lon: number; lat: number }>
export let state: SpecialVisualizationState
@ -99,7 +99,7 @@
<Tr t={Translations.t.notes.noteLayerHasFilters} />
</div>
<SubtleButton on:click={() => notelayer.disableAllFilters()}>
<Layers class="mr-4 h-8 w-8"/>
<Layers class="mr-4 h-8 w-8" />
<Tr slot="message" t={Translations.t.notes.disableAllNoteFilters} />
</SubtleButton>
</div>

View file

@ -28,11 +28,13 @@
const t = Translations.t.image.nearby
const c = [lon, lat]
console.log(">>>", image)
let attributedImage = new AttributedImage({
url: image.thumbUrl ?? image.pictureUrl,
provider: AllImageProviders.byName(image.provider),
date: new Date(image.date),
})
id: Object.values(image.osmTags)[0]
}, feature)
let distance = Math.round(
GeoOperations.distanceBetween([image.coordinates.lng, image.coordinates.lat], c)
)
@ -42,7 +44,7 @@
const key = Object.keys(image.osmTags)[0]
const url = image.osmTags[key]
if (isLinked) {
const action = new LinkImageAction(currentTags.id, key, url, currentTags, {
const action = new LinkImageAction(currentTags.id, key, url, tags, {
theme: state.layout.id,
changeType: "link-image",
})

View file

@ -35,6 +35,7 @@
)
let images: Store<P4CPicture[]> = imagesProvider.store.map((images) => images.slice(0, 20))
let allDone = imagesProvider.allDone
</script>
<div class="interactive border-interactive rounded-2xl p-2">
@ -44,8 +45,10 @@
</h4>
<slot name="corner" />
</div>
{#if $images.length === 0}
{#if !$allDone}
<Loading />
{:else if $images.length === 0}
<Tr t={Translations.t.image.nearby.noNearbyImages} cls="alert"/>
{:else}
<div class="flex w-full space-x-1 overflow-x-auto" style="scroll-snap-type: x proximity">
{#each $images as image (image.pictureUrl)}

View file

@ -11,7 +11,7 @@
import ToSvelte from "../Base/ToSvelte.svelte"
import { XCircleIcon } from "@babeard/svelte-heroicons/solid"
import exp from "constants"
import Camera_plus from "../../assets/svg/Camera_plus.svelte";
import Camera_plus from "../../assets/svg/Camera_plus.svelte"
export let tags: Store<OsmTags>
export let state: SpecialVisualizationState
@ -43,7 +43,7 @@
expanded = true
}}
>
<Camera_plus class="block w-8 h-8 p-1 mr-2"/>
<Camera_plus class="mr-2 block h-8 w-8 p-1" />
<Tr t={t.seeNearby} />
</button>
{/if}

View file

@ -67,12 +67,12 @@
},
[skippedQuestions]
)
let firstQuestion = questionsToAsk.map(qta => qta[0])
let firstQuestion = questionsToAsk.map((qta) => qta[0])
let answered: number = 0
let skipped: number = 0
function skip(question: {id: string}, didAnswer: boolean = false) {
function skip(question: { id: string }, didAnswer: boolean = false) {
skippedQuestions.data.add(question.id)
skippedQuestions.ping()
if (didAnswer) {
@ -145,25 +145,25 @@
</div>
{:else}
<TagRenderingQuestion
config={$firstQuestion}
{layer}
{selectedElement}
{state}
{tags}
on:saved={() => {
skip($firstQuestion, true)
config={$firstQuestion}
{layer}
{selectedElement}
{state}
{tags}
on:saved={() => {
skip($firstQuestion, true)
}}
>
<button
class="secondary"
on:click={() => {
skip($firstQuestion)
}}
slot="cancel"
>
<button
class="secondary"
on:click={() => {
skip($firstQuestion)
}}
slot="cancel"
>
<Tr t={Translations.t.general.skip} />
</button>
</TagRenderingQuestion>
<Tr t={Translations.t.general.skip} />
</button>
</TagRenderingQuestion>
{/if}
</div>
{/if}

View file

@ -106,7 +106,7 @@
</div>
{/if}
{:else}
<div class="w-full h-full overflow-hidden p-2">
<div class="h-full w-full overflow-hidden p-2">
<TagRenderingAnswer {config} {tags} {selectedElement} {state} {layer} />
</div>
{/if}

View file

@ -1,45 +1,56 @@
<script lang="ts">
import { ImmutableStore, UIEventSource } from "../../../Logic/UIEventSource"
import type { SpecialVisualizationState } from "../../SpecialVisualization"
import Tr from "../../Base/Tr.svelte"
import type { Feature } from "geojson"
import type { Mapping } from "../../../Models/ThemeConfig/TagRenderingConfig"
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig"
import { TagsFilter } from "../../../Logic/Tags/TagsFilter"
import FreeformInput from "./FreeformInput.svelte"
import Translations from "../../i18n/Translations.js"
import ChangeTagAction from "../../../Logic/Osm/Actions/ChangeTagAction"
import { createEventDispatcher, onDestroy } from "svelte"
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
import SpecialTranslation from "./SpecialTranslation.svelte"
import TagHint from "../TagHint.svelte"
import LoginToggle from "../../Base/LoginToggle.svelte"
import SubtleButton from "../../Base/SubtleButton.svelte"
import Loading from "../../Base/Loading.svelte"
import TagRenderingMappingInput from "./TagRenderingMappingInput.svelte"
import { Translation } from "../../i18n/Translation"
import Constants from "../../../Models/Constants"
import { Unit } from "../../../Models/Unit"
import UserRelatedState from "../../../Logic/State/UserRelatedState"
import { twJoin } from "tailwind-merge"
import { TagUtils } from "../../../Logic/Tags/TagUtils"
import { ImmutableStore, UIEventSource } from "../../../Logic/UIEventSource";
import type { SpecialVisualizationState } from "../../SpecialVisualization";
import Tr from "../../Base/Tr.svelte";
import type { Feature } from "geojson";
import type { Mapping } from "../../../Models/ThemeConfig/TagRenderingConfig";
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig";
import { TagsFilter } from "../../../Logic/Tags/TagsFilter";
import FreeformInput from "./FreeformInput.svelte";
import Translations from "../../i18n/Translations.js";
import ChangeTagAction from "../../../Logic/Osm/Actions/ChangeTagAction";
import { createEventDispatcher, onDestroy } from "svelte";
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
import SpecialTranslation from "./SpecialTranslation.svelte";
import TagHint from "../TagHint.svelte";
import LoginToggle from "../../Base/LoginToggle.svelte";
import SubtleButton from "../../Base/SubtleButton.svelte";
import Loading from "../../Base/Loading.svelte";
import TagRenderingMappingInput from "./TagRenderingMappingInput.svelte";
import { Translation } from "../../i18n/Translation";
import Constants from "../../../Models/Constants";
import { Unit } from "../../../Models/Unit";
import UserRelatedState from "../../../Logic/State/UserRelatedState";
import { twJoin } from "tailwind-merge";
import { TagUtils } from "../../../Logic/Tags/TagUtils";
import Search from "../../../assets/svg/Search.svelte";
import Login from "../../../assets/svg/Login.svelte";
export let config: TagRenderingConfig
export let tags: UIEventSource<Record<string, string>>
export let selectedElement: Feature
export let state: SpecialVisualizationState
export let layer: LayerConfig | undefined
export let config: TagRenderingConfig;
export let tags: UIEventSource<Record<string, string>>;
export let selectedElement: Feature;
export let state: SpecialVisualizationState;
export let layer: LayerConfig | undefined;
export let selectedTags: TagsFilter = undefined;
let feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined)
let feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined);
let unit: Unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key))
let unit: Unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key));
// Will be bound if a freeform is available
let freeformInput = new UIEventSource<string>(tags?.[config.freeform?.key])
let selectedMapping: number = undefined
let checkedMappings: boolean[]
let freeformInput = new UIEventSource<string>(tags?.[config.freeform?.key]);
let selectedMapping: number = undefined;
let checkedMappings: boolean[];
let mappings: Mapping[] = config?.mappings;
let searchTerm: UIEventSource<string> = new UIEventSource("");
let dispatch = createEventDispatcher<{
saved: {
config: TagRenderingConfig
applied: TagsFilter
}
}>();
/**
* Prepares and fills the checkedMappings
@ -47,12 +58,12 @@
function initialize(tgs: Record<string, string>, confg: TagRenderingConfig) {
mappings = confg.mappings?.filter((m) => {
if (typeof m.hideInAnswer === "boolean") {
return !m.hideInAnswer
return !m.hideInAnswer;
}
return !m.hideInAnswer.matchesProperties(tgs)
})
return !m.hideInAnswer.matchesProperties(tgs);
});
// We received a new config -> reinit
unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key))
unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key));
if (
confg.mappings?.length > 0 &&
@ -60,59 +71,53 @@
(checkedMappings === undefined ||
checkedMappings?.length < confg.mappings.length + (confg.freeform ? 1 : 0))
) {
const seenFreeforms = []
TagUtils.FlattenMultiAnswer()
const seenFreeforms = [];
TagUtils.FlattenMultiAnswer();
checkedMappings = [
...confg.mappings.map((mapping) => {
const matches = TagUtils.MatchesMultiAnswer(mapping.if, tgs)
const matches = TagUtils.MatchesMultiAnswer(mapping.if, tgs);
if (matches && confg.freeform) {
const newProps = TagUtils.changeAsProperties(mapping.if.asChange())
seenFreeforms.push(newProps[confg.freeform.key])
const newProps = TagUtils.changeAsProperties(mapping.if.asChange());
seenFreeforms.push(newProps[confg.freeform.key]);
}
return matches
}),
]
return matches;
})
];
if (tgs !== undefined && confg.freeform) {
const unseenFreeformValues = tgs[confg.freeform.key]?.split(";") ?? []
const unseenFreeformValues = tgs[confg.freeform.key]?.split(";") ?? [];
for (const seenFreeform of seenFreeforms) {
if (!seenFreeform) {
continue
continue;
}
const index = unseenFreeformValues.indexOf(seenFreeform)
const index = unseenFreeformValues.indexOf(seenFreeform);
if (index < 0) {
continue
continue;
}
unseenFreeformValues.splice(index, 1)
unseenFreeformValues.splice(index, 1);
}
// TODO this has _to much_ values
freeformInput.setData(unseenFreeformValues.join(";"))
checkedMappings.push(unseenFreeformValues.length > 0)
freeformInput.addCallbackAndRun(freeformValue => {
checkedMappings[checkedMappings.length - 1] = !!freeformValue
})
freeformInput.setData(unseenFreeformValues.join(";"));
checkedMappings.push(unseenFreeformValues.length > 0);
}
}
if (confg.freeform?.key) {
if (!confg.multiAnswer) {
// Somehow, setting multi-answer freeform values is broken if this is not set
freeformInput.setData(tgs[confg.freeform.key])
freeformInput.setData(tgs[confg.freeform.key]);
}
} else {
freeformInput.setData(undefined)
freeformInput.setData(undefined);
}
feedback.setData(undefined)
feedback.setData(undefined);
}
$: {
// Even though 'config' is not declared as a store, Svelte uses it as one to update the component
// We want to (re)-initialize whenever the 'tags' or 'config' change - but not when 'checkedConfig' changes
initialize($tags, config)
initialize($tags, config);
}
export let selectedTags: TagsFilter = undefined
let mappings: Mapping[] = config?.mappings
let searchTerm: UIEventSource<string> = new UIEventSource("")
$: {
try {
@ -121,10 +126,67 @@
selectedMapping,
checkedMappings,
tags.data
)
);
} catch (e) {
console.error("Could not calculate changeSpecification:", e)
selectedTags = undefined
console.error("Could not calculate changeSpecification:", e);
selectedTags = undefined;
}
}
function onSave() {
if (selectedTags === undefined) {
console.log("SelectedTags is undefined, ignoring 'onSave'-event");
return;
}
if (layer === undefined || (layer?.source === null && layer.id !== "favourite")) {
/**
* This is a special, priviliged layer.
* We simply apply the tags onto the records
*/
const kv = selectedTags.asChange(tags.data);
for (const { k, v } of kv) {
if (v === undefined || v === "") {
delete tags.data[k];
} else {
freeformInput.setData(undefined);
}
feedback.setData(undefined);
}
}
dispatch("saved", { config, applied: selectedTags });
const change = new ChangeTagAction(tags.data.id, selectedTags, tags.data, {
theme: tags.data["_orig_theme"] ?? state.layout.id,
changeType: "answer"
});
freeformInput.setData(undefined);
selectedMapping = undefined;
selectedTags = undefined;
change
.CreateChangeDescriptions()
.then((changes) => state.changes.applyChanges(changes))
.catch(console.error);
}
function onInputKeypress(e: Event) {
if (e.key === "Enter") {
onSave();
}
}
$: {
try {
selectedTags = config?.constructChangeSpecification(
$freeformInput,
selectedMapping,
checkedMappings,
tags.data
);
} catch (e) {
console.error("Could not calculate changeSpecification:", e);
selectedTags = undefined;
}
}
@ -133,85 +195,35 @@
config: TagRenderingConfig
applied: TagsFilter
}
}>()
}>();
function onSave() {
if (selectedTags === undefined) {
console.log("SelectedTags is undefined, ignoring 'onSave'-event")
return
}
if (layer === undefined || (layer?.source === null && layer.id !== "favourite")) {
/**
* This is a special, priviliged layer.
* We simply apply the tags onto the records
*/
const kv = selectedTags.asChange(tags.data)
for (const { k, v } of kv) {
if (v === undefined || v === "") {
delete tags.data[k]
} else {
tags.data[k] = v
}
}
tags.ping()
return
}
dispatch("saved", { config, applied: selectedTags })
const change = new ChangeTagAction(tags.data.id, selectedTags, tags.data, {
theme: tags.data["_orig_theme"] ?? state.layout.id,
changeType: "answer",
})
freeformInput.setData(undefined)
selectedMapping = undefined
selectedTags = undefined
change
.CreateChangeDescriptions()
.then((changes) => state.changes.applyChanges(changes))
.catch(console.error)
}
function onInputKeypress(e: Event){
if (e.key === "Enter") {
onSave();
}
}
let featureSwitchIsTesting = state?.featureSwitchIsTesting ?? new ImmutableStore(false)
let featureSwitchIsTesting = state?.featureSwitchIsTesting ?? new ImmutableStore(false);
let featureSwitchIsDebugging =
state?.featureSwitches?.featureSwitchIsDebugging ?? new ImmutableStore(false)
let showTags = state?.userRelatedState?.showTags ?? new ImmutableStore(undefined)
let numberOfCs = state?.osmConnection?.userDetails?.data?.csCount ?? 0
let question = config.question
$: question = config.question
state?.featureSwitches?.featureSwitchIsDebugging ?? new ImmutableStore(false);
let showTags = state?.userRelatedState?.showTags ?? new ImmutableStore(undefined);
let numberOfCs = state?.osmConnection?.userDetails?.data?.csCount ?? 0;
let question = config.question;
$: question = config.question;
if (state?.osmConnection) {
onDestroy(
state.osmConnection?.userDetails?.addCallbackAndRun((ud) => {
numberOfCs = ud.csCount
numberOfCs = ud.csCount;
})
)
);
}
</script>
{#if question !== undefined}
<div
class="interactive border-interactive relative flex flex-col overflow-y-auto p-1 px-2"
style="max-height: 85vh"
class="interactive border-interactive relative flex flex-col overflow-y-auto px-2"
style="max-height: 75vh"
>
<div class="sticky top-0" style="z-index: 11">
<div class="interactive sticky top-0 flex justify-between">
<div class="sticky top-0 interactive pt-1 flex justify-between" style="z-index: 11">
<span class="font-bold">
<SpecialTranslation
t={question}
{tags}
{state}
{layer}
feature={selectedElement}
/>
<SpecialTranslation t={question} {tags} {state} {layer} feature={selectedElement} />
</span>
<slot name="upper-right" />
</div>
<slot name="upper-right" />
</div>
{#if config.questionhint}
@ -228,7 +240,7 @@
{#if config.mappings?.length >= 8}
<div class="sticky flex w-full">
<Search class="h-6 w-6"/>
<Search class="h-6 w-6" />
<input type="text" bind:value={$searchTerm} class="w-full" />
</div>
{/if}
@ -263,8 +275,8 @@
bind:group={selectedMapping}
name={"mappings-radio-" + config.id}
value={i}
on:keypress={onInputKeypress}
on:keypress={e => onInputKeypress(e)}
/>
</TagRenderingMappingInput>
{/each}
@ -275,7 +287,7 @@
bind:group={selectedMapping}
name={"mappings-radio-" + config.id}
value={config.mappings?.length}
on:keypress={onInputKeypress}
on:keypress={e => onInputKeypress(e)}
/>
<FreeformInput
{config}
@ -307,7 +319,7 @@
type="checkbox"
name={"mappings-checkbox-" + config.id + "-" + i}
bind:checked={checkedMappings[i]}
on:keypress={onInputKeypress}
on:keypress={e => onInputKeypress(e)}
/>
</TagRenderingMappingInput>
{/each}
@ -317,7 +329,7 @@
type="checkbox"
name={"mappings-checkbox-" + config.id + "-" + config.mappings?.length}
bind:checked={checkedMappings[config.mappings.length]}
on:keypress={onInputKeypress}
on:keypress={e => onInputKeypress(e)}
/>
<FreeformInput
{config}

View file

@ -12,7 +12,7 @@
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
import ToSvelte from "../Base/ToSvelte.svelte"
import Svg from "../../Svg"
import Mangrove_logo from "../../assets/svg/Mangrove_logo.svelte";
import Mangrove_logo from "../../assets/svg/Mangrove_logo.svelte"
/**
* An element showing all reviews
@ -41,7 +41,7 @@
<Tr t={Translations.t.reviews.no_reviews_yet} />
{/if}
<div class="flex justify-end">
<Mangrove_logo class="w-12 h-12 shrink-0 p-1"/>
<Mangrove_logo class="h-12 w-12 shrink-0 p-1" />
<Tr cls="text-sm subtle" t={Translations.t.reviews.attribution} />
</div>
</div>

View file

@ -2,9 +2,9 @@
import ToSvelte from "../Base/ToSvelte.svelte"
import Svg from "../../Svg"
import { createEventDispatcher } from "svelte"
import Star from "../../assets/svg/Star.svelte";
import Star_half from "../../assets/svg/Star_half.svelte";
import Star_outline from "../../assets/svg/Star_outline.svelte";
import Star from "../../assets/svg/Star.svelte"
import Star_half from "../../assets/svg/Star_half.svelte"
import Star_outline from "../../assets/svg/Star_outline.svelte"
export let score: number
export let cutoff: number
@ -26,10 +26,10 @@
on:mousemove={(e) => dispatch("hover", { score: getScore(e) })}
>
{#if score >= cutoff}
<Star class={starSize}/>
<Star class={starSize} />
{:else if score + 10 >= cutoff}
<Star_half class={starSize}/>
<Star_half class={starSize} />
{:else}
<Star_outline class={starSize}/>
<Star_outline class={starSize} />
{/if}
</div>

View file

@ -90,7 +90,7 @@ export interface SpecialVisualization {
readonly funcName: string
readonly docs: string | BaseUIElement
readonly example?: string
readonly needsUrls: string[]
readonly needsUrls: string[] | ((args: string[]) => string)
/**
* Indicates that this special visualisation will make requests to the 'alLNodesDatabase' and that it thus should be included

View file

@ -659,7 +659,7 @@ export default class SpecialVisualizations {
},
],
needsUrls: AllImageProviders.apiUrls,
constr: (state, tags, args) => {
constr: (state, tags, args, feature) => {
let imagePrefixes: string[] = undefined
if (args.length > 0) {
imagePrefixes = [].concat(...args.map((a) => a.split(",")))
@ -667,7 +667,8 @@ export default class SpecialVisualizations {
return new ImageCarousel(
AllImageProviders.LoadImagesFor(tags, imagePrefixes),
tags,
state
state,
feature
)
},
},
@ -1461,7 +1462,7 @@ export default class SpecialVisualizations {
},
],
docs: "Shows events that are happening based on a Giggity URL",
needsUrls: ["*"],
needsUrls: (args) => args[0],
constr(
state: SpecialVisualizationState,
tagSource: UIEventSource<Record<string, string>>,

View file

@ -10,13 +10,14 @@
export let info: { id: string; owner: number };
export let category: "layers" | "themes";
export let osmConnection: OsmConnection;
const dispatch = createEventDispatcher<{ layerSelected: string }>();
let displayName = UIEventSource.FromPromise(
osmConnection.getInformationAboutUser(info.owner)
).mapD((response) => response.display_name);
let selfId = osmConnection.userDetails.mapD((ud) => ud.uid);
function fetchIconDescription(layerId): any {
if (category === "themes") {
return AllKnownLayouts.allKnownLayouts.get(layerId).icon;
@ -24,7 +25,6 @@
return AllSharedLayers.getSharedLayersConfigs().get(layerId)?._layerIcon;
}
const dispatch = createEventDispatcher<{ layerSelected: string }>();
</script>
<NextButton clss="small" on:click={() => dispatch("layerSelected", info)}>
@ -33,12 +33,14 @@
</div>
<b class="px-1">{info.id}</b>
{#if info.owner && info.owner !== $selfId}
{#if displayName}
{#if $displayName}
(made by {$displayName}
{#if window.location.host.startsWith("127.0.0.1")}
- {info.owner}
{/if}
)
{:else }
({info.owner})
{/if}
{/if}
</NextButton>

View file

@ -9,7 +9,7 @@
import { Utils } from "../../Utils"
import type { ConversionMessage } from "../../Models/ThemeConfig/Conversion/Conversion"
import ErrorIndicatorForRegion from "./ErrorIndicatorForRegion.svelte"
import { ChevronRightIcon } from "@rgossiaux/svelte-heroicons/solid"
import { ChevronRightIcon, TrashIcon } from "@rgossiaux/svelte-heroicons/solid"
import SchemaBasedInput from "./SchemaBasedInput.svelte"
import FloatOver from "../Base/FloatOver.svelte"
import TagRenderingInput from "./TagRenderingInput.svelte"
@ -21,6 +21,7 @@
const layerSchema: ConfigMeta[] = <any>layerSchemaRaw
export let state: EditLayerState
export let backToStudio: () => void
let messages = state.messages
let hasErrors = messages.mapD(
(m: ConversionMessage[]) => m.filter((m) => m.level === "error").length
@ -72,6 +73,10 @@
})
let highlightedItem: UIEventSource<HighlightedTagRendering> = state.highlightedItem
function deleteLayer() {
state.delete()
backToStudio()
}
</script>
<div class="flex h-screen flex-col">
@ -113,6 +118,12 @@
</div>
<div class="flex flex-col" slot="content0">
<Region {state} configs={perRegion["Basic"]} />
<div class="mt-12">
<button on:click={() => deleteLayer()} class="small" >
<TrashIcon class="h-6 w-6"/> Delete this layer
</button>
</div>
</div>
<div slot="title1" class="flex">

View file

@ -107,6 +107,9 @@ export abstract class EditJsonState<T> {
return entry
}
public async delete(){
await this.server.delete(this.getId().data, this.category)
}
public getStoreFor<T>(path: ReadonlyArray<string | number>): UIEventSource<T | undefined> {
const key = path.join(".")
@ -294,16 +297,39 @@ export default class EditLayerState extends EditJsonState<LayerConfigJson> {
this.addMissingTagRenderingIds()
this.configuration.addCallbackAndRunD((layer) => {
if (layer.tagRenderings) {
function cleanArray(data: object, key: string): boolean{
if(!data){
return false
}
if (data[key]) {
// A bit of cleanup
const lBefore = layer.tagRenderings.length
const cleaned = Utils.NoNull(layer.tagRenderings)
const lBefore = data[key].length
const cleaned = Utils.NoNull(data[key])
if (cleaned.length != lBefore) {
layer.tagRenderings = cleaned
this.configuration.ping()
data[key] = cleaned
return true
}
}
return false
}
this.configuration.addCallbackAndRunD((layer) => {
let changed = cleanArray(layer, "tagRenderings") || cleanArray(layer, "pointRenderings")
for (const tr of layer.tagRenderings ?? []) {
if(typeof tr === "string"){
continue
}
const qtr = (<QuestionableTagRenderingConfigJson> tr)
if(qtr.freeform && Object.keys(qtr.freeform ).length === 0){
delete qtr.freeform
changed = true
}
}
if(changed){
this.configuration.ping()
}
})
}

View file

@ -64,7 +64,16 @@
}
}
newPath.push(...toAdd)
console.log("Fused path ", path.join("."), "+", i,"+", subpartPath.join("."),"into",newPath.join("."))
console.log(
"Fused path ",
path.join("."),
"+",
i,
"+",
subpartPath.join("."),
"into",
newPath.join(".")
)
return newPath
}

View file

@ -58,7 +58,14 @@ export default class StudioServer {
return undefined
}
}
async delete(id: string, category: "layers" | "themes") {
if (id === undefined || id === "") {
return
}
await fetch(this.urlFor(id, category), {
method: "DELETE"
})
}
async update(id: string, config: string, category: "layers" | "themes") {
if (id === undefined || id === "") {
return

View file

@ -3,104 +3,104 @@
* Little helper class to deal with choosing a builtin tagRendering or defining one yourself.
* Breaks the ideology that everything should be schema based
*/
import EditLayerState from "./EditLayerState";
import type { ConfigMeta } from "./configMeta";
import EditLayerState from "./EditLayerState"
import type { ConfigMeta } from "./configMeta"
import type {
MappingConfigJson,
QuestionableTagRenderingConfigJson
} from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson";
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig";
import TagRenderingEditable from "../Popup/TagRendering/TagRenderingEditable.svelte";
import { Store, UIEventSource } from "../../Logic/UIEventSource";
import * as questions from "../../assets/generated/layers/questions.json";
import MappingInput from "./MappingInput.svelte";
import { TrashIcon } from "@rgossiaux/svelte-heroicons/outline";
import questionableTagRenderingSchemaRaw from "../../assets/schemas/questionabletagrenderingconfigmeta.json";
import SchemaBasedField from "./SchemaBasedField.svelte";
import Region from "./Region.svelte";
import NextButton from "../Base/NextButton.svelte";
import { QuestionMarkCircleIcon } from "@rgossiaux/svelte-heroicons/solid";
import { LocalStorageSource } from "../../Logic/Web/LocalStorageSource";
import { onMount } from "svelte";
QuestionableTagRenderingConfigJson,
} from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson"
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"
import TagRenderingEditable from "../Popup/TagRendering/TagRenderingEditable.svelte"
import { Store, UIEventSource } from "../../Logic/UIEventSource"
import * as questions from "../../assets/generated/layers/questions.json"
import MappingInput from "./MappingInput.svelte"
import { TrashIcon } from "@rgossiaux/svelte-heroicons/outline"
import questionableTagRenderingSchemaRaw from "../../assets/schemas/questionabletagrenderingconfigmeta.json"
import SchemaBasedField from "./SchemaBasedField.svelte"
import Region from "./Region.svelte"
import NextButton from "../Base/NextButton.svelte"
import { QuestionMarkCircleIcon } from "@rgossiaux/svelte-heroicons/solid"
import { LocalStorageSource } from "../../Logic/Web/LocalStorageSource"
import { onMount } from "svelte"
export let state: EditLayerState;
export let schema: ConfigMeta;
export let path: (string | number)[];
let expertMode = state.expertMode;
const store = state.getStoreFor(path);
let value = store.data;
export let state: EditLayerState
export let schema: ConfigMeta
export let path: (string | number)[]
let expertMode = state.expertMode
const store = state.getStoreFor(path)
let value = store.data
let hasSeenIntro = UIEventSource.asBoolean(
LocalStorageSource.Get("studio-seen-tagrendering-tutorial", "false")
);
)
onMount(() => {
if (!hasSeenIntro.data) {
state.showIntro.setData("tagrenderings");
hasSeenIntro.setData(true);
state.showIntro.setData("tagrenderings")
hasSeenIntro.setData(true)
}
});
})
/**
* Allows the theme builder to create 'writable' themes.
* Should only be enabled for 'tagrenderings' in the theme, if the source is OSM
*/
let allowQuestions: Store<boolean> = state.configuration.mapD(
(config) => path.at(0) === "tagRenderings" && config.source?.geoJson === undefined
);
)
let mappingsBuiltin: MappingConfigJson[] = [];
let perLabel: Record<string, MappingConfigJson> = {};
let mappingsBuiltin: MappingConfigJson[] = []
let perLabel: Record<string, MappingConfigJson> = {}
for (const tr of questions.tagRenderings) {
let description = tr["description"] ?? tr["question"] ?? "No description available";
description = description["en"] ?? description;
let description = tr["description"] ?? tr["question"] ?? "No description available"
description = description["en"] ?? description
if (tr["labels"]) {
const labels: string[] = tr["labels"];
const labels: string[] = tr["labels"]
for (const label of labels) {
let labelMapping: MappingConfigJson = perLabel[label];
let labelMapping: MappingConfigJson = perLabel[label]
if (!labelMapping) {
labelMapping = {
if: "value=" + label,
then: {
en: "Builtin collection <b>" + label + "</b>:"
}
};
perLabel[label] = labelMapping;
mappingsBuiltin.push(labelMapping);
en: "Builtin collection <b>" + label + "</b>:",
},
}
perLabel[label] = labelMapping
mappingsBuiltin.push(labelMapping)
}
labelMapping.then.en = labelMapping.then.en + "<div>" + description + "</div>";
labelMapping.then.en = labelMapping.then.en + "<div>" + description + "</div>"
}
}
mappingsBuiltin.push({
if: "value=" + tr["id"],
then: {
en: "Builtin <b>" + tr["id"] + "</b> <div class='subtle'>" + description + "</div>"
}
});
en: "Builtin <b>" + tr["id"] + "</b> <div class='subtle'>" + description + "</div>",
},
})
}
const configBuiltin = new TagRenderingConfig(<QuestionableTagRenderingConfigJson>{
question: "Which builtin element should be shown?",
mappings: mappingsBuiltin
});
mappings: mappingsBuiltin,
})
const tags = new UIEventSource({ value });
const tags = new UIEventSource({ value })
tags.addCallbackAndRunD((tgs) => {
store.setData(tgs["value"]);
});
store.setData(tgs["value"])
})
let mappings: UIEventSource<MappingConfigJson[]> = state.getStoreFor([...path, "mappings"]);
let mappings: UIEventSource<MappingConfigJson[]> = state.getStoreFor([...path, "mappings"])
const topLevelItems: Record<string, ConfigMeta> = {};
const topLevelItems: Record<string, ConfigMeta> = {}
for (const item of questionableTagRenderingSchemaRaw) {
if (item.path.length === 1) {
topLevelItems[item.path[0]] = <ConfigMeta>item;
topLevelItems[item.path[0]] = <ConfigMeta>item
}
}
function initMappings() {
if (mappings.data === undefined) {
mappings.setData([]);
mappings.setData([])
}
}
@ -113,28 +113,25 @@
"condition",
"metacondition",
"mappings",
"icon"
]);
const ignored = new Set(["labels", "description", "classes"]);
"icon",
])
const ignored = new Set(["labels", "description", "classes"])
const freeformSchemaAll = <ConfigMeta[]>(
questionableTagRenderingSchemaRaw.filter(
(schema) =>
schema.path.length == 2 &&
schema.path[0] === "freeform" &&
($allowQuestions)
(schema) => schema.path.length == 2 && schema.path[0] === "freeform" && $allowQuestions
)
);
)
let freeformSchema = $expertMode
? freeformSchemaAll
: freeformSchemaAll.filter((schema) => schema.hints?.group !== "expert");
: freeformSchemaAll.filter((schema) => schema.hints?.group !== "expert")
const missing: string[] = questionableTagRenderingSchemaRaw
.filter(
(schema) =>
schema.path.length >= 1 && !items.has(schema.path[0]) && !ignored.has(schema.path[0])
)
.map((schema) => schema.path.join("."));
console.log({ state });
.map((schema) => schema.path.join("."))
console.log({ state })
</script>
{#if typeof $store === "string"}

View file

@ -15,7 +15,6 @@
import If from "./Base/If.svelte"
import BackButton from "./Base/BackButton.svelte"
import ChooseLayerToEdit from "./Studio/ChooseLayerToEdit.svelte"
import { LocalStorageSource } from "../Logic/Web/LocalStorageSource"
import FloatOver from "./Base/FloatOver.svelte"
import Walkthrough from "./Walkthrough/Walkthrough.svelte"
import * as intro from "../assets/studio_introduction.json"
@ -26,10 +25,10 @@
import EditTheme from "./Studio/EditTheme.svelte"
import * as meta from "../../package.json"
import Checkbox from "./Base/Checkbox.svelte"
import { Utils } from "../Utils";
import Translations from "./i18n/Translations";
import Tr from "./Base/Tr.svelte";
import Add from "../assets/svg/Add.svelte";
import { Utils } from "../Utils"
import Translations from "./i18n/Translations"
import Tr from "./Base/Tr.svelte"
import Add from "../assets/svg/Add.svelte"
export let studioUrl =
window.location.hostname === "127.0.0.2"
@ -155,7 +154,7 @@
Contact <a href="https://app.element.io/#/room/#MapComplete:matrix.org">
the MapComplete community via the chat.
</a>
Someone might be able to help you
Someone might be able to help you
</li>
<li>
File <a href="https://github.com/pietervdvn/MapComplete/issues">an issue</a>
@ -197,7 +196,7 @@
<QuestionMarkCircleIcon class="h-6 w-6" />
Show the introduction again
</button>
<a class="flex button" href={Utils.HomepageLink()}>
<a class="button flex" href={Utils.HomepageLink()}>
<Add class="h-6 w-6" />
<Tr t={Translations.t.general.backToIndex} />
</a>
@ -261,7 +260,7 @@
<Loading />
</div>
{:else if state === "editing_layer"}
<EditLayer state={editLayerState}>
<EditLayer state={editLayerState} backToStudio={() => {state = undefined}}>
<BackButton
clss="small p-1"
imageClass="w-8 h-8"
@ -285,22 +284,23 @@
</BackButton>
</EditTheme>
{/if}
</LoginToggle>
</If>
{#if { intro, tagrenderings: intro_tagrenderings }[$showIntro]?.sections}
<FloatOver
on:close={() => {
{#if { intro, tagrenderings: intro_tagrenderings }[$showIntro]?.sections}
<FloatOver
on:close={() => {
showIntro.setData("no")
}}
>
<div class="flex h-full p-4 pr-12">
<Walkthrough
pages={{ intro, tagrenderings: intro_tagrenderings }[$showIntro]?.sections}
on:done={() => {
>
<div class="flex h-full p-4 pr-12">
<Walkthrough
pages={{ intro, tagrenderings: intro_tagrenderings }[$showIntro]?.sections}
on:done={() => {
showIntro.setData("no")
}}
/>
</div>
</FloatOver>
{/if}
/>
</div>
</FloatOver>
{/if}
</LoginToggle>
</If>

View file

@ -1,8 +1,8 @@
<script lang="ts">
import Svg from "../Svg";
import Loading from "./Base/Loading.svelte";
import ToSvelte from "./Base/ToSvelte.svelte";
import Community from "../assets/svg/Community.svelte";
import Svg from "../Svg"
import Loading from "./Base/Loading.svelte"
import ToSvelte from "./Base/ToSvelte.svelte"
import Community from "../assets/svg/Community.svelte"
</script>
<div>
@ -41,30 +41,29 @@
<div class="flex">
<button class="primary">
<Community class="w-6 h-6" />
<Community class="h-6 w-6" />
Main action
</button>
<button class="primary disabled">
<Community class="w-6 h-6" />
<Community class="h-6 w-6" />
Main action (disabled)
</button>
<button class="small">
<Community class="w-6 h-6" />
<Community class="h-6 w-6" />
Small button
</button>
<button class="small primary">Small button</button>
<button class="small primary disabled">Small, disabled button</button>
</div>
<div class="flex">
<button>
<Community class="w-6 h-6" />
<Community class="h-6 w-6" />
Secondary action
</button>
<button class="disabled">
<Community class="w-6 h-6" />
<Community class="h-6 w-6" />
Secondary action (disabled)
</button>
</div>
@ -83,7 +82,7 @@
</label>
<label for="javascript">
<input id="javascript" name="fav_language" type="radio" value="JavaScript" />
<Community class="w-8 h-8"/>
<Community class="h-8 w-8" />
JavaScript
</label>
</div>
@ -107,26 +106,26 @@
<div class="flex">
<button class="primary">
<Community class="w-6 h-6" />
<Community class="h-6 w-6" />
Main action
</button>
<button class="primary disabled">
<Community class="w-6 h-6" />
<Community class="h-6 w-6" />
Main action (disabled)
</button>
<button class="small">
<Community class="w-6 h-6" />
<Community class="h-6 w-6" />
Small button
</button>
</div>
<div class="flex">
<button>
<Community class="w-6 h-6" />
<Community class="h-6 w-6" />
Secondary action
</button>
<button class="disabled">
<Community class="w-6 h-6" />
<Community class="h-6 w-6" />
Secondary action (disabled)
</button>
</div>

View file

@ -1,16 +1,5 @@
<script lang="ts">
// Testing grounds
import MarkAsFavourite from "./Popup/MarkAsFavourite.svelte";
import { UIEventSource } from "../Logic/UIEventSource";
import { OsmConnection } from "../Logic/Osm/OsmConnection";
const osmConnection = new OsmConnection({attemptLogin: true})
function resetFavs(){
osmConnection.preferencesHandler.removeAllWithPrefix("mapcomplete-favourite-")
console.log("CLEARED!")
}
</script>
<button on:click={() => resetFavs()} >Clear</button>
<div class="w-full">No tests</div>

View file

@ -65,13 +65,78 @@
import Download from "../assets/svg/Download.svelte";
import Share from "../assets/svg/Share.svelte";
import Favourites from "./Favourites/Favourites.svelte";
import { Store, UIEventSource } from "../Logic/UIEventSource"
import { Map as MlMap } from "maplibre-gl"
import MaplibreMap from "./Map/MaplibreMap.svelte"
import FeatureSwitchState from "../Logic/State/FeatureSwitchState"
import MapControlButton from "./Base/MapControlButton.svelte"
import ToSvelte from "./Base/ToSvelte.svelte"
import If from "./Base/If.svelte"
import { GeolocationControl } from "./BigComponents/GeolocationControl"
import type { Feature } from "geojson"
import SelectedElementView from "./BigComponents/SelectedElementView.svelte"
import LayerConfig from "../Models/ThemeConfig/LayerConfig"
import Filterview from "./BigComponents/Filterview.svelte"
import ThemeViewState from "../Models/ThemeViewState"
import type { MapProperties } from "../Models/MapProperties"
import Geosearch from "./BigComponents/Geosearch.svelte"
import Translations from "./i18n/Translations"
import { CogIcon, EyeIcon, MenuIcon, XCircleIcon } from "@rgossiaux/svelte-heroicons/solid"
import Tr from "./Base/Tr.svelte"
import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte"
import FloatOver from "./Base/FloatOver.svelte"
import PrivacyPolicy from "./BigComponents/PrivacyPolicy"
import Constants from "../Models/Constants"
import TabbedGroup from "./Base/TabbedGroup.svelte"
import UserRelatedState from "../Logic/State/UserRelatedState"
import LoginToggle from "./Base/LoginToggle.svelte"
import LoginButton from "./Base/LoginButton.svelte"
import CopyrightPanel from "./BigComponents/CopyrightPanel"
import DownloadPanel from "./DownloadFlow/DownloadPanel.svelte"
import ModalRight from "./Base/ModalRight.svelte"
import { Utils } from "../Utils"
import Hotkeys from "./Base/Hotkeys"
import { VariableUiElement } from "./Base/VariableUIElement"
import SvelteUIElement from "./Base/SvelteUIElement"
import OverlayToggle from "./BigComponents/OverlayToggle.svelte"
import LevelSelector from "./BigComponents/LevelSelector.svelte"
import ExtraLinkButton from "./BigComponents/ExtraLinkButton"
import SelectedElementTitle from "./BigComponents/SelectedElementTitle.svelte"
import ThemeIntroPanel from "./BigComponents/ThemeIntroPanel.svelte"
import type { RasterLayerPolygon } from "../Models/RasterLayers"
import { AvailableRasterLayers } from "../Models/RasterLayers"
import RasterLayerOverview from "./Map/RasterLayerOverview.svelte"
import IfHidden from "./Base/IfHidden.svelte"
import { onDestroy } from "svelte"
import MapillaryLink from "./BigComponents/MapillaryLink.svelte"
import OpenIdEditor from "./BigComponents/OpenIdEditor.svelte"
import OpenBackgroundSelectorButton from "./BigComponents/OpenBackgroundSelectorButton.svelte"
import StateIndicator from "./BigComponents/StateIndicator.svelte"
import ShareScreen from "./BigComponents/ShareScreen.svelte"
import UploadingImageCounter from "./Image/UploadingImageCounter.svelte"
import PendingChangesIndicator from "./BigComponents/PendingChangesIndicator.svelte"
import Cross from "../assets/svg/Cross.svelte"
import Summary from "./BigComponents/Summary.svelte"
import Mastodon from "../assets/svg/Mastodon.svelte"
import Bug from "../assets/svg/Bug.svelte"
import Liberapay from "../assets/svg/Liberapay.svelte"
import Min from "../assets/svg/Min.svelte"
import Plus from "../assets/svg/Plus.svelte"
import Filter from "../assets/svg/Filter.svelte"
import Add from "../assets/svg/Add.svelte"
import Statistics from "../assets/svg/Statistics.svelte"
import Community from "../assets/svg/Community.svelte"
import Download from "../assets/svg/Download.svelte"
import Share from "../assets/svg/Share.svelte"
import LanguagePicker from "./InputElement/LanguagePicker.svelte"
import OpenJosm from "./Base/OpenJosm.svelte"
export let state: ThemeViewState;
let layout = state.layout;
export let state: ThemeViewState
let layout = state.layout
let maplibremap: UIEventSource<MlMap> = state.map;
let selectedElement: UIEventSource<Feature> = state.selectedElement;
let selectedLayer: UIEventSource<LayerConfig> = state.selectedLayer;
let maplibremap: UIEventSource<MlMap> = state.map
let selectedElement: UIEventSource<Feature> = state.selectedElement
let selectedLayer: UIEventSource<LayerConfig> = state.selectedLayer
let currentZoom = state.mapProperties.zoom;
let showCrosshair = state.userRelatedState.showCrosshair;
@ -87,50 +152,50 @@
return undefined;
}
if (!(layer.tagRenderings?.length > 0) || layer.title === undefined) {
return undefined;
}
if (!(layer.tagRenderings?.length > 0) || layer.title === undefined) {
return undefined
}
const tags = state.featureProperties.getStore(selectedElement.properties.id);
return new SvelteUIElement(SelectedElementView, {
state,
layer,
selectedElement,
tags
}).SetClass("h-full w-full");
},
[selectedLayer]
);
const tags = state.featureProperties.getStore(selectedElement.properties.id)
return new SvelteUIElement(SelectedElementView, {
state,
layer,
selectedElement,
tags,
}).SetClass("h-full w-full")
},
[selectedLayer],
)
const selectedElementTitle = selectedElement.map(
(selectedElement) => {
// Svelte doesn't properly reload some of the legacy UI-elements
// As such, we _reconstruct_ the selectedElementView every time a new feature is selected
// This is a bit wasteful, but until everything is a svelte-component, this should do the trick
const layer = selectedLayer.data;
if (selectedElement === undefined || layer === undefined) {
return undefined;
}
const selectedElementTitle = selectedElement.map(
(selectedElement) => {
// Svelte doesn't properly reload some of the legacy UI-elements
// As such, we _reconstruct_ the selectedElementView every time a new feature is selected
// This is a bit wasteful, but until everything is a svelte-component, this should do the trick
const layer = selectedLayer.data
if (selectedElement === undefined || layer === undefined) {
return undefined
}
const tags = state.featureProperties.getStore(selectedElement.properties.id);
return new SvelteUIElement(SelectedElementTitle, { state, layer, selectedElement, tags });
},
[selectedLayer]
);
const tags = state.featureProperties.getStore(selectedElement.properties.id)
return new SvelteUIElement(SelectedElementTitle, { state, layer, selectedElement, tags })
},
[selectedLayer],
)
let mapproperties: MapProperties = state.mapProperties;
let featureSwitches: FeatureSwitchState = state.featureSwitches;
let availableLayers = state.availableLayers;
let userdetails = state.osmConnection.userDetails;
let currentViewLayer = layout.layers.find((l) => l.id === "current_view");
let rasterLayer: Store<RasterLayerPolygon> = state.mapProperties.rasterLayer;
let rasterLayerName =
rasterLayer.data?.properties?.name ?? AvailableRasterLayers.maptilerDefaultLayer.properties.name;
onDestroy(
rasterLayer.addCallbackAndRunD((l) => {
rasterLayerName = l.properties.name;
})
);
let mapproperties: MapProperties = state.mapProperties
let featureSwitches: FeatureSwitchState = state.featureSwitches
let availableLayers = state.availableLayers
let userdetails = state.osmConnection.userDetails
let currentViewLayer = layout.layers.find((l) => l.id === "current_view")
let rasterLayer: Store<RasterLayerPolygon> = state.mapProperties.rasterLayer
let rasterLayerName =
rasterLayer.data?.properties?.name ?? AvailableRasterLayers.maptilerDefaultLayer.properties.name
onDestroy(
rasterLayer.addCallbackAndRunD((l) => {
rasterLayerName = l.properties.name
}),
)
</script>
<div class="absolute top-0 left-0 h-screen w-screen overflow-hidden">
@ -214,7 +279,7 @@
<!-- bottom left elements -->
<If condition={state.featureSwitches.featureSwitchFilter}>
<MapControlButton on:click={() => state.guistate.openFilterView()}>
<Filter class="h-6 w-6"/>
<Filter class="h-6 w-6" />
</MapControlButton>
</If>
<If condition={state.featureSwitches.featureSwitchBackgroundSelection}>
@ -253,10 +318,10 @@
</div>
</If>
<MapControlButton on:click={() => mapproperties.zoom.update((z) => z + 1)}>
<Plus class="w-8 h-8" />
<Plus class="h-8 w-8" />
</MapControlButton>
<MapControlButton on:click={() => mapproperties.zoom.update((z) => z - 1)}>
<Min class="w-8 h-8"/>
<Min class="h-8 w-8" />
</MapControlButton>
<If condition={featureSwitches.featureSwitchGeolocation}>
<MapControlButton>
@ -272,7 +337,7 @@
</div>
<LoginToggle ignoreLoading={true} {state}>
{#if ($showCrosshair === "yes" && $currentZoom >= 17) || $showCrosshair === "always" || $arrowKeysWereUsed !== undefined }
{#if ($showCrosshair === "yes" && $currentZoom >= 17) || $showCrosshair === "always" || $arrowKeysWereUsed !== undefined}
<div
class="pointer-events-none absolute top-0 left-0 flex h-full w-full items-center justify-center"
>
@ -349,7 +414,7 @@
</div>
<div class="flex" slot="title1">
<Filter class="w-4 h-4"/>
<Filter class="h-4 w-4" />
<Tr t={Translations.t.general.menu.filter} />
</div>
@ -373,7 +438,7 @@
<div class="flex" slot="title2">
<If condition={state.featureSwitches.featureSwitchEnableExport}>
<Download class="w-4 h-4"/>
<Download class="h-4 w-4" />
<Tr t={Translations.t.general.download.title} />
</If>
</div>
@ -388,7 +453,7 @@
<ToSvelte construct={() => new CopyrightPanel(state)} slot="content3" />
<div class="flex" slot="title4">
<Share class="w-4 h-4"/>
<Share class="h-4 w-4" />
<Tr t={Translations.t.general.sharescreen.title} />
</div>
<div class="m-2" slot="content4">
@ -440,17 +505,17 @@
<Tr t={Translations.t.general.aboutMapComplete.intro} />
<a class="flex" href={Utils.HomepageLink()}>
<Add class="h-6 w-6"/>
<Add class="h-6 w-6" />
<Tr t={Translations.t.general.backToIndex} />
</a>
<a class="flex" href="https://github.com/pietervdvn/MapComplete/issues" target="_blank">
<Bug class="h-6 w-6"/>
<Bug class="h-6 w-6" />
<Tr t={Translations.t.general.attribution.openIssueTracker} />
</a>
<a class="flex" href="https://en.osm.town/@MapComplete" target="_blank">
<Mastodon class="w-6 h-6" />
<Mastodon class="h-6 w-6" />
<Tr t={Translations.t.general.attribution.followOnMastodon} />
</a>
@ -495,15 +560,15 @@
<div class="flex" slot="title2">
<HeartIcon class="h-6 w-6" />
Your favourites
<Tr t={Translations.t.favouritePoi.tab}/>
</div>
<div class="flex flex-col m-2" slot="content2">
<h3>Your favourite locations</h3>
<h3> <Tr t={Translations.t.favouritePoi.title}/></h3>
<Favourites {state}/>
</div>
<div class="flex" slot="title3">
<Community class="w-6 h-6"/>
<Community class="h-6 w-6" />
<Tr t={Translations.t.communityIndex.title} />
</div>
<div class="m-2" slot="content3">
@ -521,7 +586,7 @@
<div class="m-2 flex flex-col" slot="content5">
<If condition={featureSwitches.featureSwitchEnableLogin}>
<OpenIdEditor mapProperties={state.mapProperties} />
<OpenJosm {state}/>
<OpenJosm {state} />
<MapillaryLink mapProperties={state.mapProperties} />
</If>

View file

@ -1,25 +1,24 @@
<script lang="ts">
import BackButton from "../Base/BackButton.svelte";
import NextButton from "../Base/NextButton.svelte";
import { createEventDispatcher } from "svelte";
import BackButton from "../Base/BackButton.svelte"
import NextButton from "../Base/NextButton.svelte"
import { createEventDispatcher } from "svelte"
const dispatch = createEventDispatcher<{ back; next }>();
export let islast = false;
export let isFirst = false;
export let pageNumber: number = undefined;
export let totalPages: number = undefined;
const dispatch = createEventDispatcher<{ back; next }>()
export let islast = false
export let isFirst = false
export let pageNumber: number = undefined
export let totalPages: number = undefined
</script>
<div class="flex h-full w-full flex-col justify-between link-underline">
<div class="link-underline flex h-full w-full flex-col justify-between">
<div class="overflow-y-auto">
<slot />
</div>
<div class="flex flex-col">
{#if pageNumber !== undefined && totalPages !== undefined}
<div class="flex justify-end">
<div class="subtle">{pageNumber+1}/{totalPages}</div>
<div class="subtle">{pageNumber + 1}/{totalPages}</div>
</div>
{/if}
<div class="flex w-full">
@ -35,8 +34,6 @@
Next
{/if}
</NextButton>
</div>
</div>
</div>

View file

@ -9,7 +9,7 @@
import WikidataPreviewBox from "./WikidataPreviewBox"
import Tr from "../Base/Tr.svelte"
import Translations from "../i18n/Translations"
import Wikipedia from "../../assets/svg/Wikipedia.svelte";
import Wikipedia from "../../assets/svg/Wikipedia.svelte"
/**
* Shows a wikipedia-article + wikidata preview for the given item
@ -19,7 +19,7 @@
{#if $wikipediaDetails.articleUrl}
<a class="flex" href={$wikipediaDetails.articleUrl} rel="noreferrer" target="_blank">
<Wikipedia class="h-6 w-6"/>
<Wikipedia class="h-6 w-6" />
<Tr t={Translations.t.general.wikipedia.fromWikipedia} />
</a>
{/if}

View file

@ -11,7 +11,7 @@ export class Utils {
public static readonly assets_path = "./assets/svg/"
public static externalDownloadFunction: (
url: string,
headers?: any
headers?: any,
) => Promise<{ content: string } | { redirect: string }>
public static Special_visualizations_tagsToApplyHelpText = `These can either be a tag to add, such as \`amenity=fast_food\` or can use a substitution, e.g. \`addr:housenumber=$number\`.
This new point will then have the tags \`amenity=fast_food\` and \`addr:housenumber\` with the value that was saved in \`number\` in the original feature.
@ -150,7 +150,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
if (Utils.runningFromConsole) {
return
}
DOMPurify.addHook("afterSanitizeAttributes", function (node) {
DOMPurify.addHook("afterSanitizeAttributes", function(node) {
// set all elements owning target to target=_blank + add noopener noreferrer
const target = node.getAttribute("target")
if (target) {
@ -172,7 +172,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
*/
public static ParseVisArgs(
specs: { name: string; defaultValue?: string }[],
args: string[]
args: string[],
): Record<string, string> {
const parsed: Record<string, string> = {}
if (args.length > specs.length) {
@ -324,7 +324,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
object: any,
name: string,
init: () => any,
whenDone?: () => void
whenDone?: () => void,
) {
Object.defineProperty(object, name, {
enumerable: false,
@ -347,7 +347,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
object: any,
name: string,
init: () => Promise<any>,
whenDone?: () => void
whenDone?: () => void,
) {
Object.defineProperty(object, name, {
enumerable: false,
@ -487,7 +487,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
public static SubstituteKeys(
txt: string | undefined,
tags: Record<string, any> | undefined,
useLang?: string
useLang?: string,
): string | undefined {
if (txt === undefined) {
return undefined
@ -523,7 +523,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
"SubstituteKeys received a BaseUIElement to substitute in - this is probably a bug and will be downcast to a string\nThe key is",
key,
"\nThe value is",
v
v,
)
v = v.InnerConstructElement()?.textContent
}
@ -565,38 +565,6 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
target.push(...source)
}
/**
* Recursively rewrites all keys from `+key`, `key+` and `=key` into `key
*
* Utils.CleanMergeObject({"condition":{"and+":["xyz"]}} // => {"condition":{"and":["xyz"]}}
* @param obj
* @constructor
* @private
*/
private static CleanMergeObject(obj: any) {
if (Array.isArray(obj)) {
const result = []
for (const el of obj) {
result.push(Utils.CleanMergeObject(el))
}
return result
}
if (typeof obj !== "object") {
return obj
}
const newObj = {}
for (let objKey in obj) {
let cleanKey = objKey
if (objKey.startsWith("+") || objKey.startsWith("=")) {
cleanKey = objKey.substring(1)
} else if (objKey.endsWith("+") || objKey.endsWith("=")) {
cleanKey = objKey.substring(0, objKey.length - 1)
}
newObj[cleanKey] = Utils.CleanMergeObject(obj[objKey])
}
return newObj
}
/**
* Copies all key-value pairs of the source into the target. This will change the target
* If the key starts with a '+', the values of the list will be appended to the target instead of overwritten
@ -668,7 +636,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
if (!Array.isArray(targetV)) {
throw new Error(
"Cannot concatenate: value to add is not an array: " +
JSON.stringify(targetV)
JSON.stringify(targetV),
)
}
if (Array.isArray(sourceV)) {
@ -676,9 +644,9 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
} else {
throw new Error(
"Could not merge concatenate " +
JSON.stringify(sourceV) +
" and " +
JSON.stringify(targetV)
JSON.stringify(sourceV) +
" and " +
JSON.stringify(targetV),
)
}
} else {
@ -723,7 +691,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
path: string[],
object: any,
replaceLeaf: (leaf: any, travelledPath: string[]) => any,
travelledPath: string[] = []
travelledPath: string[] = [],
): void {
if (object == null) {
return
@ -754,7 +722,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
}
if (Array.isArray(sub)) {
sub.forEach((el, i) =>
Utils.WalkPath(path.slice(1), el, replaceLeaf, [...travelledPath, head, "" + i])
Utils.WalkPath(path.slice(1), el, replaceLeaf, [...travelledPath, head, "" + i]),
)
return
}
@ -771,7 +739,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
path: string[],
object: any,
collectedList: { leaf: any; path: string[] }[] = [],
travelledPath: string[] = []
travelledPath: string[] = [],
): { leaf: any; path: string[] }[] {
if (object === undefined || object === null) {
return collectedList
@ -801,7 +769,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
if (Array.isArray(sub)) {
sub.forEach((el, i) =>
Utils.CollectPath(path.slice(1), el, collectedList, [...travelledPath, "" + i])
Utils.CollectPath(path.slice(1), el, collectedList, [...travelledPath, "" + i]),
)
return collectedList
}
@ -845,7 +813,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
json: any,
f: (v: object | number | string | boolean | undefined, path: string[]) => any,
isLeaf: (object) => boolean = undefined,
path: string[] = []
path: string[] = [],
) {
if (json === undefined || json === null) {
return f(json, path)
@ -884,7 +852,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
json: any,
collect: (v: number | string | boolean | undefined, path: string[]) => any,
isLeaf: (object) => boolean = undefined,
path = []
path = [],
): void {
if (json === undefined) {
return
@ -959,7 +927,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
continue
}
const i = part.charCodeAt(0)
result += '"' + keys[i] + '":' + part.substring(1)
result += "\"" + keys[i] + "\":" + part.substring(1)
}
return result
@ -986,7 +954,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
url: string,
headers?: any,
method: "POST" | "GET" | "PUT" | "UPDATE" | "DELETE" | "OPTIONS" = "GET",
content?: string
content?: string,
): Promise<
| { content: string }
| { redirect: string }
@ -1051,7 +1019,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
public static async downloadJsonCached(
url: string,
maxCacheTimeMs: number,
headers?: any
headers?: any,
): Promise<any> {
const result = await Utils.downloadJsonAdvanced(url, headers)
if (result["content"]) {
@ -1063,7 +1031,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
public static async downloadJsonCachedAdvanced(
url: string,
maxCacheTimeMs: number,
headers?: any
headers?: any,
): Promise<{ content: any } | { error: string; url: string; statuscode?: number }> {
const cached = Utils._download_cache.get(url)
if (cached !== undefined) {
@ -1073,9 +1041,9 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
}
const promise =
/*NO AWAIT as we work with the promise directly */ Utils.downloadJsonAdvanced(
url,
headers
)
url,
headers,
)
Utils._download_cache.set(url, { promise, timestamp: new Date().getTime() })
return await promise
}
@ -1090,7 +1058,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
public static async downloadJsonAdvanced(
url: string,
headers?: any
headers?: any,
): Promise<{ content: any } | { error: string; url: string; statuscode?: number }> {
const injected = Utils.injectedDownloads[url]
if (injected !== undefined) {
@ -1099,7 +1067,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
}
const result = await Utils.downloadAdvanced(
url,
Utils.Merge({ accept: "application/json" }, headers ?? {})
Utils.Merge({ accept: "application/json" }, headers ?? {}),
)
if (result["error"] !== undefined) {
return <{ error: string; url: string; statuscode?: number }>result
@ -1119,7 +1087,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
"due to",
e,
"\n",
e.stack
e.stack,
)
return { error: "malformed", url }
}
@ -1140,7 +1108,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
| "{gpx=application/gpx+xml}"
| "application/json"
| "image/png"
}
},
) {
const element = document.createElement("a")
let file
@ -1244,7 +1212,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
e.preventDefault()
return false
},
false
false,
)
}
@ -1328,7 +1296,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
public static sortedByLevenshteinDistance<T>(
reference: string,
ts: T[],
getName: (t: T) => string
getName: (t: T) => string,
): T[] {
const withDistance: [T, number][] = ts.map((t) => [
t,
@ -1354,7 +1322,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
track[j][i] = Math.min(
track[j][i - 1] + 1, // deletion
track[j - 1][i] + 1, // insertion
track[j - 1][i - 1] + indicator // substitution
track[j - 1][i - 1] + indicator, // substitution
)
}
}
@ -1363,7 +1331,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
public static MapToObj<V, T>(
d: Map<string, V>,
onValue: (t: V, key: string) => T
onValue: (t: V, key: string) => T,
): Record<string, T> {
const o = {}
const keys = Array.from(d.keys())
@ -1380,7 +1348,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
* Utils.TransposeMap({"a" : ["b", "c"], "x" : ["b", "y"]}) // => {"b" : ["a", "x"], "c" : ["a"], "y" : ["x"]}
*/
public static TransposeMap<K extends string, V extends string>(
d: Record<K, V[]>
d: Record<K, V[]>,
): Record<V, K[]> {
const newD: Record<V, K[]> = <any>{}
@ -1454,7 +1422,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
}
public static asDict(
tags: { key: string; value: string | number }[]
tags: { key: string; value: string | number }[],
): Map<string, string | number> {
const d = new Map<string, string | number>()
@ -1495,21 +1463,6 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
element.scrollIntoView({ behavior: "smooth", block: "nearest" })
}
private static findParentWithScrolling(element: HTMLBaseElement): HTMLBaseElement {
// Check if the element itself has scrolling
if (element.scrollHeight > element.clientHeight) {
return element
}
// If the element does not have scrolling, check if it has a parent element
if (!element.parentElement) {
return null
}
// If the element has a parent, repeat the process for the parent element
return Utils.findParentWithScrolling(<HTMLBaseElement>element.parentElement)
}
/**
* Returns true if the contents of `a` are the same (and in the same order) as `b`.
* Might have false negatives in some cases
@ -1576,7 +1529,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
*
*/
public static splitIntoSubstitutionParts(
template: string
template: string,
): ({ message: string } | { subs: string })[] {
const preparts = template.split("{")
const spec: ({ message: string } | { subs: string })[] = []
@ -1637,6 +1590,13 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
}
}
public static RemoveDiacritics(str?: string): string {
if(!str){
return str
}
return str.normalize("NFD").replace(/\p{Diacritic}/gu, "")
}
public static randomString(length: number): string {
let result = ""
for (let i = 0; i < length; i++) {
@ -1645,9 +1605,57 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
}
return result
}
/**
* Recursively rewrites all keys from `+key`, `key+` and `=key` into `key
*
* Utils.CleanMergeObject({"condition":{"and+":["xyz"]}} // => {"condition":{"and":["xyz"]}}
* @param obj
* @constructor
* @private
*/
private static CleanMergeObject(obj: any) {
if (Array.isArray(obj)) {
const result = []
for (const el of obj) {
result.push(Utils.CleanMergeObject(el))
}
return result
}
if (typeof obj !== "object") {
return obj
}
const newObj = {}
for (let objKey in obj) {
let cleanKey = objKey
if (objKey.startsWith("+") || objKey.startsWith("=")) {
cleanKey = objKey.substring(1)
} else if (objKey.endsWith("+") || objKey.endsWith("=")) {
cleanKey = objKey.substring(0, objKey.length - 1)
}
newObj[cleanKey] = Utils.CleanMergeObject(obj[objKey])
}
return newObj
}
private static findParentWithScrolling(element: HTMLBaseElement): HTMLBaseElement {
// Check if the element itself has scrolling
if (element.scrollHeight > element.clientHeight) {
return element
}
// If the element does not have scrolling, check if it has a parent element
if (!element.parentElement) {
return null
}
// If the element has a parent, repeat the process for the parent element
return Utils.findParentWithScrolling(<HTMLBaseElement>element.parentElement)
}
private static colorDiff(
c0: { r: number; g: number; b: number },
c1: { r: number; g: number; b: number }
c1: { r: number; g: number; b: number },
) {
return Math.abs(c0.r - c1.r) + Math.abs(c0.g - c1.g) + Math.abs(c0.b - c1.b)
}

View file

@ -1,7 +1,7 @@
{
"contributors": [
{
"commits": 6315,
"commits": 6418,
"contributor": "Pieter Vander Vennet"
},
{
@ -50,11 +50,11 @@
},
{
"commits": 24,
"contributor": "Ward"
"contributor": "dependabot[bot]"
},
{
"commits": 23,
"contributor": "dependabot[bot]"
"commits": 24,
"contributor": "Ward"
},
{
"commits": 21,

View file

@ -12,7 +12,7 @@
"gl": "lingua galega",
"he": "עברית",
"hu": "magyar",
"id": "bahasa Indonesia",
"id": "Indonesia",
"it": "italiano",
"ja": "日本語",
"nb_NO": "bokmål",
@ -23,6 +23,5 @@
"ru": "русский язык",
"sl": "slovenščina",
"sv": "svenska",
"zh_Hans": "简体中文",
"zh_Hant": "繁體中文"
"zh_Hant": "簡體中文"
}

View file

@ -146,7 +146,7 @@
"gl": "Lingua adigue",
"he": "אדיגית",
"hu": "adigei",
"id": "bahasa Adyghe",
"id": "Adyghe",
"it": "adighè",
"ja": "アディゲ語",
"nb_NO": "adygeisk",
@ -603,7 +603,7 @@
"gl": "árabe",
"he": "ערבית",
"hu": "arab",
"id": "bahasa Arab",
"id": "Arab",
"it": "arabo",
"ja": "アラビア語",
"nb_NO": "arabisk",
@ -929,7 +929,7 @@
"fi": "Awadhin kieli",
"fr": "awadhi",
"gl": "Lingua awadhi",
"he": "אוודהית",
"he": "אוודית",
"id": "Bahasa Awadhi",
"it": "awadhi",
"ja": "アワディー語",
@ -1603,7 +1603,7 @@
"gl": "lingua bretoa",
"he": "ברטונית",
"hu": "breton",
"id": "Bahasa Breton",
"id": "Breton",
"it": "bretone",
"ja": "ブルトン語",
"nb_NO": "bretonsk",
@ -1772,7 +1772,7 @@
"gl": "Lingua buriata",
"he": "בוריאטית",
"hu": "burját",
"id": "bahasa Buryat",
"id": "Buryat",
"it": "buriato",
"ja": "ブリヤート語",
"nb_NO": "burjatisk",
@ -2316,7 +2316,7 @@
"gl": "Lingua tártara de Crimea",
"he": "טטרית של קרים",
"hu": "krími tatár",
"id": "Bahasa Tatar Krimea",
"id": "Tatar Krimea",
"it": "tataro di Crimea",
"ja": "クリミア・タタール語",
"nb_NO": "krimtatarisk",
@ -2442,6 +2442,7 @@
"id": "Bahasa Chittagonia",
"it": "lingua chittagonian",
"ja": "チッタゴン語",
"nb_NO": "Chittagong",
"pl": "Język chatgaya",
"pt": "Língua chittagong",
"pt_BR": "Língua chittagong",
@ -2532,7 +2533,7 @@
"gl": "lingua dinamarquesa",
"he": "דנית",
"hu": "dán",
"id": "bahasa Denmark",
"id": "Denmark",
"it": "danese",
"ja": "デンマーク語",
"nb_NO": "dansk",
@ -2595,7 +2596,7 @@
"gl": "lingua alemá",
"he": "גרמנית",
"hu": "német",
"id": "bahasa Jerman",
"id": "Jerman",
"it": "tedesco",
"ja": "ドイツ語",
"nb_NO": "tysk",
@ -2966,8 +2967,8 @@
"ru": "новогреческий язык",
"sl": "novogrščina",
"sv": "nygrekiska",
"zh_Hans": "希腊语",
"zh_Hant": "希臘語",
"zh_Hans": "现代希腊语",
"zh_Hant": "現代希臘語",
"_meta": {
"countries": [
"CY",
@ -3583,7 +3584,7 @@
"gl": "lingua feroesa",
"he": "פארואזית",
"hu": "feröeri",
"id": "bahasa Faroe",
"id": "Faroe",
"it": "faroese",
"ja": "フェロー語",
"nb_NO": "færøysk",
@ -4871,7 +4872,7 @@
"gl": "lingua indonesia",
"he": "אינדונזית",
"hu": "indonéz",
"id": "bahasa Indonesia",
"id": "Indonesia",
"it": "indonesiano",
"ja": "インドネシア語",
"nb_NO": "indonesisk",
@ -5018,7 +5019,7 @@
"gl": "lingua islandesa",
"he": "איסלנדית",
"hu": "izlandi",
"id": "bahasa Islandia",
"id": "Islandia",
"it": "islandese",
"ja": "アイスランド語",
"nb_NO": "islandsk",
@ -5054,7 +5055,7 @@
"gl": "lingua italiana",
"he": "איטלקית",
"hu": "olasz",
"id": "bahasa Italia",
"id": "Italia",
"it": "italiano",
"ja": "イタリア語",
"nb_NO": "italiensk",
@ -5126,7 +5127,7 @@
"gl": "lingua xaponesa",
"he": "יפנית",
"hu": "japán",
"id": "bahasa Jepang",
"id": "Jepang",
"it": "giapponese",
"ja": "日本語",
"nb_NO": "japansk",
@ -5209,7 +5210,7 @@
"gl": "Lingua xavanesa",
"he": "ג'אווה",
"hu": "jávai",
"id": "bahasa Jawa",
"id": "Jawa",
"it": "giavanese",
"ja": "ジャワ語",
"nb_NO": "javanesisk",
@ -5246,7 +5247,7 @@
"gl": "lingua xeorxiana",
"he": "גאורגית",
"hu": "grúz",
"id": "Bahasa Georgia",
"id": "Georgia",
"it": "georgiano",
"ja": "ジョージア語",
"nb_NO": "georgisk",
@ -5281,7 +5282,7 @@
"gl": "Lingua karakalpak",
"he": "קראקלפקית",
"hu": "karakalpak",
"id": "Bahasa Karakalpak",
"id": "Karakalpak",
"it": "karakalpako",
"ja": "カラカルパク語",
"nl": "Karakalpaks",
@ -5465,6 +5466,7 @@
"ja": "カインガング語",
"nb_NO": "Kaingang",
"nl": "Kaingang",
"pl": "Języki caingang",
"pt": "Língua caingangue",
"pt_BR": "Língua kaingáng",
"ru": "Каинганг",
@ -5635,7 +5637,7 @@
"gl": "Lingua casaca",
"he": "קזחית",
"hu": "kazak",
"id": "bahasa Kazakh",
"id": "Kazakh",
"it": "kazako",
"ja": "カザフ語",
"nb_NO": "kasakhisk",
@ -5672,7 +5674,7 @@
"gl": "Lingua grenlandesa",
"he": "גרינלנדית",
"hu": "grönlandi",
"id": "bahasa Greenland",
"id": "Greenland",
"it": "groenlandese",
"ja": "グリーンランド語",
"nb_NO": "grønlandsk",
@ -5704,7 +5706,7 @@
"gl": "Lingua khmer",
"he": "קמרית",
"hu": "khmer",
"id": "bahasa Khmer",
"id": "Khmer",
"it": "khmer",
"ja": "クメール語",
"nb_NO": "khmer",
@ -5815,6 +5817,7 @@
"pl": "język komi-permiacki",
"pt": "Língua komi-permyak",
"ru": "коми-пермяцкий язык",
"sl": "permjaščina",
"sv": "komi-permjakiska",
"zh_Hans": "彼尔姆科米语",
"zh_Hant": "彼爾姆科米語",
@ -6024,32 +6027,32 @@
}
},
"ku": {
"ca": "kurd del nord",
"cs": "kurmándží",
"da": "Kurmanji",
"de": "Kurmandschi",
"en": "Kurmanji",
"eo": "kurmanĝa lingvo",
"es": "kurmanji",
"eu": "Kurmanji",
"fi": "Kurmandži",
"fr": "kurmandji",
"ca": "kurd",
"cs": "kurdština",
"da": "kurdisk",
"de": "Kurdisch",
"en": "Kurdish",
"eo": "kurda lingvo",
"es": "kurdo",
"eu": "kurduera",
"fi": "kurdi",
"fr": "kurde",
"gl": "lingua kurda",
"he": "כורמנג'ית",
"hu": "kurmandzsi",
"id": "Kurmanji",
"it": "kurmanji",
"ja": "クルマンジー",
"he": "כורדית",
"hu": "kurd",
"id": "Bahasa Kurdi",
"it": "curdo",
"ja": "クルド語",
"nb_NO": "kurdisk",
"nl": "Kurmançi",
"pl": "język kurmandżi",
"pt": "curmânji",
"pt_BR": "Curmânji",
"ru": "курманджи",
"sl": "kurmandži",
"sv": "nordkurdiska",
"nl": "Koerdisch",
"pl": "język kurdyjski",
"pt": "língua curda",
"pt_BR": "língua curda",
"ru": "курдские языки",
"sl": "kurdščina",
"sv": "kurdiska",
"zh_Hans": "库尔德语",
"zh_Hant": "庫德語",
"zh_Hant": "庫德語",
"_meta": {
"countries": [
"IQ"
@ -6126,7 +6129,7 @@
"gl": "lingua komi",
"he": "קומי",
"hu": "komi",
"id": "Bahasa Komi",
"id": "Komi",
"it": "comi",
"ja": "コミ語",
"nb_NO": "syrjensk",
@ -6134,6 +6137,7 @@
"pl": "język komi",
"pt": "língua komi",
"ru": "коми язык",
"sl": "komijščina",
"sv": "komi",
"_meta": {
"dir": [
@ -6216,7 +6220,7 @@
"gl": "kirguiz",
"he": "קירגיזית",
"hu": "kirgiz",
"id": "bahasa Kirgiz",
"id": "Kirgiz",
"it": "kirghiso",
"ja": "キルギス語",
"nb_NO": "kirgisisk",
@ -6302,7 +6306,7 @@
"gl": "Lingua luxemburguesa",
"he": "לוקסמבורגית",
"hu": "luxemburgi",
"id": "bahasa Luksemburg",
"id": "Luksemburg",
"it": "lussemburghese",
"ja": "ルクセンブルク語",
"nb_NO": "luxembourgsk",
@ -6542,7 +6546,7 @@
"gl": "Lingua lombarda",
"he": "לומברד (שפה)",
"hu": "lombard",
"id": "bahasa Lombard",
"id": "Lombard",
"it": "lingua lombarda",
"ja": "ロンバルド語",
"nb_NO": "lombardisk",
@ -6602,7 +6606,7 @@
"gl": "Lingua laosiana",
"he": "לאית",
"hu": "lao",
"id": "bahasa Lao",
"id": "Lao",
"it": "lao",
"ja": "ラーオ語",
"nb_NO": "laotisk",
@ -6972,7 +6976,7 @@
"gl": "Lingua malgaxe",
"he": "מלגשית",
"hu": "malgas",
"id": "Bahasa Malagasi",
"id": "Malagasi",
"it": "malgascio",
"ja": "マダガスカル語",
"nb_NO": "gassisk",
@ -7158,7 +7162,7 @@
"gl": "Lingua macedonia",
"he": "מקדונית",
"hu": "macedón",
"id": "bahasa Makedonia",
"id": "Makedonia",
"it": "macedone",
"ja": "マケドニア語",
"nb_NO": "makedonsk",
@ -7226,7 +7230,7 @@
"gl": "Lingua mongol",
"he": "מונגולית",
"hu": "mongol",
"id": "bahasa Mongol",
"id": "Mongol",
"it": "mongolo",
"ja": "モンゴル語",
"nb_NO": "mongolsk",
@ -7467,7 +7471,7 @@
"gl": "lingua malaia",
"he": "מלאית",
"hu": "maláj",
"id": "bahasa Melayu",
"id": "Melayu",
"it": "malese",
"ja": "マレー語",
"nb_NO": "malayisk",
@ -7645,7 +7649,7 @@
"gl": "birmano",
"he": "בורמזית",
"hu": "burmai",
"id": "bahasa Burma",
"id": "Burma",
"it": "birmano",
"ja": "ビルマ語",
"nb_NO": "burmesisk",
@ -8107,7 +8111,7 @@
"gl": "lingua norueguesa",
"he": "נורווגית",
"hu": "norvég",
"id": "bahasa Norwegia",
"id": "Norwegia",
"it": "norvegese",
"ja": "ノルウェー語",
"nb_NO": "norsk",
@ -8434,12 +8438,12 @@
"eo": "olonec-karela lingvo",
"fi": "livvinkarjala",
"fr": "olonetsien",
"gl": "Lingua livvi",
"gl": "lingua livvi",
"it": "lingua livvi",
"ja": "リッヴィ語",
"nb_NO": "livvisk",
"nl": "Olonetsisch",
"pl": "Dialekt ołoniecki",
"pl": "dialekt ołoniecki",
"ru": "ливвиковское наречие",
"sv": "livvi",
"zh_Hant": "利維卡累利阿語",
@ -8544,7 +8548,7 @@
"gl": "Lingua oseta",
"he": "אוסטית",
"hu": "oszét",
"id": "bahasa Ossetia",
"id": "Ossetia",
"it": "osseto",
"ja": "オセット語",
"nb_NO": "ossetisk",
@ -8620,7 +8624,7 @@
"gl": "lingua punjabi (Shahmukhi)",
"he": "פנג'אבי (אלפבית שאהמוקי)",
"hu": "pandzsábi (Shahmukhi)",
"id": "Bahasa Punjab (Abjad Shahmukhi)",
"id": "Punjab (Abjad Shahmukhi)",
"it": "punjabi (Shahmukhī)",
"ja": "パンジャーブ語 (シャームキー文字)",
"nb_NO": "panjabi (Shahmukhi)",
@ -8845,6 +8849,7 @@
"pl": "Język neosalomoński",
"pt": "Língua pijin",
"ru": "Пиджин Соломоновых Островов",
"sl": "salomonski pidžin",
"sv": "pijin",
"_meta": {
"dir": [
@ -9042,7 +9047,7 @@
"gl": "lingua portuguesa",
"he": "פורטוגזית",
"hu": "portugál",
"id": "bahasa Portugis",
"id": "Portugis",
"it": "portoghese",
"ja": "ポルトガル語",
"nb_NO": "portugisisk",
@ -9252,7 +9257,7 @@
"en": "Rakhine",
"fr": "arakanais",
"gl": "Lingua arakanesa",
"id": "bahasa Rakhine",
"id": "Rakhine",
"ja": "ラカイン語",
"nl": "Arakanees",
"pl": "Język arakański",
@ -9500,7 +9505,7 @@
"gl": "Lingua arromanesa",
"he": "ארומנית",
"hu": "aromán",
"id": "Bahasa Arumania",
"id": "Arumania",
"it": "arumeno",
"ja": "アルーマニア語",
"nb_NO": "arumensk",
@ -9895,7 +9900,7 @@
"ca": "taixelhit",
"cs": "tašelhit",
"de": "Taschelhit",
"en": "Shilha",
"en": "Tachelhit",
"eo": "ŝelha lingvo",
"es": "chilha",
"fi": "Tašelhit",
@ -9995,7 +10000,7 @@
"pt": "Língua cingalesa",
"pt_BR": "Língua cingalesa",
"ru": "сингальский язык",
"sl": "sinhalščina",
"sl": "singalščina",
"sv": "singalesiska",
"zh_Hant": "僧伽羅語",
"_meta": {
@ -10455,7 +10460,7 @@
"gl": "Lingua albanesa",
"he": "אלבנית",
"hu": "albán",
"id": "Bahasa Albania",
"id": "Albania",
"it": "albanese",
"ja": "アルバニア語",
"nb_NO": "albansk",
@ -10698,7 +10703,7 @@
"gl": "lingua sueca",
"he": "שוודית",
"hu": "svéd",
"id": "bahasa Swedia",
"id": "Swedia",
"it": "svedese",
"ja": "スウェーデン語",
"nb_NO": "svensk",
@ -10797,7 +10802,7 @@
"gl": "Lingua silesiana",
"he": "שלזית",
"hu": "sziléziai",
"id": "bahasa Silesia",
"id": "Silesia",
"it": "slesiano",
"ja": "シレジア語",
"nb_NO": "schlesisk",
@ -10846,7 +10851,7 @@
"gl": "Lingua támil",
"he": "טמילית",
"hu": "tamil",
"id": "Bahasa Tamil",
"id": "Tamil",
"it": "tamil",
"ja": "タミル語",
"nb_NO": "tamilsk",
@ -11033,7 +11038,7 @@
"gl": "lingua tailandesa",
"he": "תאית",
"hu": "thai",
"id": "bahasa Thai",
"id": "Thai",
"it": "thailandese",
"ja": "タイ語",
"nb_NO": "thai",
@ -11103,7 +11108,7 @@
"gl": "Lingua turcomá",
"he": "טורקמנית",
"hu": "türkmén",
"id": "bahasa Turkmen",
"id": "Turkmen",
"it": "Turkmeno",
"ja": "トルクメン語",
"nb_NO": "turkmensk",
@ -11631,7 +11636,7 @@
"gl": "Lingua uigur",
"he": "אויגורית",
"hu": "ujgur",
"id": "bahasa Uyghur",
"id": "Uighur",
"it": "uiguro",
"ja": "ウイグル語",
"nb_NO": "uigurisk",
@ -11701,7 +11706,7 @@
"gl": "Lingua usbeka",
"he": "אוזבקית",
"hu": "üzbég",
"id": "bahasa Uzbek",
"id": "Uzbek",
"it": "uzbeco",
"ja": "ウズベク語",
"nb_NO": "usbekisk",
@ -12590,7 +12595,7 @@
"gl": "lingua chinesa",
"he": "סינית",
"hu": "kínai",
"id": "bahasa Tionghoa",
"id": "Tionghoa",
"it": "cinese",
"ja": "中国語",
"nb_NO": "kinesisk",
@ -12646,7 +12651,7 @@
]
}
},
"zh_Hans": {
"zh_Hant": {
"ca": "xinès simplificat",
"cs": "zjednodušená čínština",
"da": "forenklet kinesisk",
@ -12655,6 +12660,7 @@
"eo": "simpligita ĉina skribsistemo",
"es": "chino simplificado",
"eu": "Txinera sinplifikatua",
"fi": "perinteinen kiina",
"fr": "chinois simplifié",
"gl": "chinés simplificado",
"he": "סינית מפושטת",
@ -12677,36 +12683,6 @@
]
}
},
"zh_Hant": {
"ca": "xinès tradicional",
"cs": "čínština (tradiční)",
"da": "traditionel kinesisk",
"de": "traditionelles Chinesisch",
"en": "Traditional Chinese",
"eo": "ĉina lingvo de tradicia ortografio",
"es": "chino tradicional",
"eu": "Txinera tradizional",
"fi": "perinteinen kiina",
"fr": "chinois traditionnel",
"gl": "chinés tradicional",
"he": "סינית מסורתית",
"it": "cinese tradizionale",
"ja": "繁体字中国語",
"nb_NO": "tradisjonell kinesisk",
"nl": "traditioneel Chinees",
"pl": "język chiński tradycyjny",
"pt": "chinês tradicional",
"ru": "традиционный китайский",
"sl": "tradicionalna kitajščina",
"sv": "traditionell kinesiska",
"zh_Hans": "繁体中文",
"zh_Hant": "繁體中文",
"_meta": {
"dir": [
"left-to-right"
]
}
},
"zu": {
"ca": "zulu",
"cs": "zuluština",

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
{"sections":["# How to work with TagRenderings\n\nThe information box shows various attributes of the selected feature in a human friendly way.\n\nThis is done by a **tagRendering** which converts attributes into text.\n\nThis can be done by using **predefined options** (mappings) or with a **render**-string\n","# Predefined options\n\nA predefined option states that, `if` a certain tag is present, `then` a certain text should be shown.\n\nFor example, a playground may be lit or not.\nIn OpenStreetMap, this is encoded with the tag `lit=yes` or `lit=no`. We might want to show `This playground is lit at night` and `This playground is not lit at night` to users of MapComplete.\n\nThis is what this will look like in the interface:\n\n<img class=\"w-1/2\" src=\"./assets/docs/PredefinedOption.png\"/>\n","# Substituting attributes\n\nIf none of the predefined options match, the string given in the `render`-field is used (under the question _\"What text should be rendered?\"_).\n\nA special property about all shown texts is that, **if the name of a key appears between braces, this will be replaced by the corresponding value**.\n\nFor example, if the object has tags `min_age=3` and the text to display is `Accessible to kids older than {min_age} years`, then this will be displayed to the user as **Accessible to kids older than 3 years**\n\nNote that this also works withing predifined options\n","# Special values\n\nSpecial components can be summoned by calling them. For example, the relevant wikipedia will be displayed by entering the text `{wikipedia()}`. A table with opening hours is displayed with `{opening_hours()}`. For a full reference, [see the documentation](../SpecialRenderings.md).\n","# Requesting data with predefined options\n\nThese renderings can be turned into a way to contribute data easily. If a **question** is provided, then these renderings will be asked if unknown or gain the pencil to make changes. \n\nA predefined option will show up as an option that can be picked.\n<img class=\"w-1/2\" src=\"./assets/docs/QuestionPredefinedOptions.png\"/>\n","# Requesting data with an input field\n\nIt is also possible to have a text field. For this, the **key** to write into must be given (_What is the name of the attribute that should be written to?_), in this case `max_age`.\n<img class=\"w-1/2\" src=\"./assets/docs/QuestionTextField.png\"/>\n","# Combining predefined options and freeform text\n\nA text field and predefined options can be combined. The contributor can then choose between a predefined option or filling out something.\n<img class=\"w-1/2\" src=\"./assets/docs/QuestionCombined.png\"/>\n","# Selecting multiple values\n\nOne can set a question to allow multiple answers. This works with predefined options or a freeform text field.\n\n<img class=\"w-1/2\" src=\"./assets/docs/QuestionMulti.png\"/>\n\nNote that these will be rendered as a list:\n\n<img class=\"w-1/2\" src=\"./assets/docs/RenderMulti.png\"/>\n"]}
{"sections":["# How to work with TagRenderings\n\nThe information box shows various attributes of the selected feature in a human friendly way.\n\nThis is done by a **tagRendering** which converts attributes into text.\n\nThis can be done by using **predefined options** (mappings) or with a **render**-string\n","# Predefined options\n\nA predefined option states that, `if` a certain tag is present, `then` a certain text should be shown.\n\nFor example, a playground may be lit or not.\nIn OpenStreetMap, this is encoded with the tag `lit=yes` or `lit=no`. We might want to show `This playground is lit at night` and `This playground is not lit at night` to users of MapComplete.\n\nThis is what this will look like in the interface:\n\n<img class=\"w-1/2\" src=\"./assets/docs/PredefinedOption.png\"/>\n","# Substituting attributes\n\nIf none of the predefined options match, the string given in the `render`-field is used (under the question _\"What text should be rendered?\"_).\n\nA special property about all shown texts is that, **if the name of a key appears between braces, this will be replaced by the corresponding value**.\n\nFor example, if the object has tags `min_age=3` and the text to display is `Accessible to kids older than {min_age} years`, then this will be displayed to the user as **Accessible to kids older than 3 years**\n\nNote that this also works withing predifined options\n","# Special values\n\nSpecial components can be summoned by calling them. For example, the relevant wikipedia will be displayed by entering the text `{wikipedia()}`. A table with opening hours is displayed with `{opening_hours()}`. For a full reference, [see the documentation](https://github.com/pietervdvn/MapComplete/blob/master/Docs/SpecialRenderings.md).\n","# Requesting data with predefined options\n\nThese renderings can be turned into a way to contribute data easily. If a **question** is provided, then these renderings will be asked if unknown or gain the pencil to make changes. \n\nA predefined option will show up as an option that can be picked.\n<img class=\"w-1/2\" src=\"./assets/docs/QuestionPredefinedOptions.png\"/>\n","# Requesting data with an input field\n\nIt is also possible to have a text field. For this, the **key** to write into must be given (_What is the name of the attribute that should be written to?_), in this case `max_age`.\n<img class=\"w-1/2\" src=\"./assets/docs/QuestionTextField.png\"/>\n","# Combining predefined options and freeform text\n\nA text field and predefined options can be combined. The contributor can then choose between a predefined option or filling out something.\n<img class=\"w-1/2\" src=\"./assets/docs/QuestionCombined.png\"/>\n","# Selecting multiple values\n\nOne can set a question to allow multiple answers. This works with predefined options or a freeform text field.\n\n<img class=\"w-1/2\" src=\"./assets/docs/QuestionMulti.png\"/>\n\nNote that these will be rendered as a list:\n\n<img class=\"w-1/2\" src=\"./assets/docs/RenderMulti.png\"/>\n"]}

View file

@ -1,4 +1,38 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="303px" height="374px" viewBox="0 0 303 374" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(43.921569%,77.254903%,28.627452%);fill-opacity:1;" d="M 163.890625 344.988281 C 158.277344 356.675781 141.632812 356.675781 136.019531 344.988281 L 41.4375 148.097656 C 36.507812 137.839844 43.988281 125.953125 55.375 125.953125 L 244.535156 125.953125 C 255.917969 125.953125 263.398438 137.839844 258.46875 148.097656 Z M 163.890625 344.988281 "/> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(43.921569%,77.254903%,28.627452%);fill-opacity:1;" d="M 303 151.453125 C 303 235.101562 235.171875 302.910156 151.5 302.910156 C 67.828125 302.910156 0 235.101562 0 151.453125 C 0 67.808594 67.828125 0 151.5 0 C 235.171875 0 303 67.808594 303 151.453125 Z M 303 151.453125 "/> <path style="fill: none !important;stroke-width:7.514114;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 22.101015 291.358766 L 5.785842 275.043593 " transform="matrix(4.837809,-4.836357,4.837809,4.836357,-1287.063942,-1153.71106)"/> <path style="fill: none !important;stroke-width:7.514114;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 22.125279 274.965231 L 5.810459 291.28005 " transform="matrix(4.837809,-4.836357,4.837809,4.836357,-1287.063942,-1153.71106)"/> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
width="303px"
height="374px"
viewBox="0 0 303 374"
version="1.1"
>
<g id="surface1">
<path
style=" stroke:none;fill-rule:nonzero;fill:rgb(43.921569%,77.254903%,28.627452%);fill-opacity:1;"
d="M 163.890625 344.988281 C 158.277344 356.675781 141.632812 356.675781 136.019531 344.988281 L 41.4375 148.097656 C 36.507812 137.839844 43.988281 125.953125 55.375 125.953125 L 244.535156 125.953125 C 255.917969 125.953125 263.398438 137.839844 258.46875 148.097656 Z M 163.890625 344.988281 "
/>
<path
style=" stroke:none;fill-rule:nonzero;fill:rgb(43.921569%,77.254903%,28.627452%);fill-opacity:1;"
d="M 303 151.453125 C 303 235.101562 235.171875 302.910156 151.5 302.910156 C 67.828125 302.910156 0 235.101562 0 151.453125 C 0 67.808594 67.828125 0 151.5 0 C 235.171875 0 303 67.808594 303 151.453125 Z M 303 151.453125 "
/>
<path
style="fill: none !important;stroke-width:7.514114;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;"
d="M 22.101015 291.358766 L 5.785842 275.043593 "
transform="matrix(4.837809,-4.836357,4.837809,4.836357,-1287.063942,-1153.71106)"
/>
<path
style="fill: none !important;stroke-width:7.514114;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;"
d="M 22.125279 274.965231 L 5.810459 291.28005 "
transform="matrix(4.837809,-4.836357,4.837809,4.836357,-1287.063942,-1153.71106)"
/>
</g>
</svg>

View file

@ -1,4 +1,29 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill-rule:nonzero;fill:rgb(21.568628%,83.92157%,28.627452%);fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(37.64706%,37.64706%,37.64706%);stroke-opacity:1;stroke-miterlimit:4;" d="M 98 49.021438 C 98 76.083729 76.062292 98.021438 49 98.021438 C 21.937708 98.021438 0 76.083729 0 49.021438 C 0 21.959146 21.937708 0.0214375 49 0.0214375 C 76.062292 0.0214375 98 21.959146 98 49.021438 Z M 98 49.021438 " transform="matrix(3.826531,0,0,3.826531,0,0)"/> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 185.398438 53.390625 C 176.808594 53.523438 168.636719 57.125 162.738281 63.378906 C 157.074219 69.394531 153.96875 77.378906 154.085938 85.640625 L 154.085938 152.132812 L 88.527344 152.132812 C 79.929688 152.011719 71.644531 155.371094 65.566406 161.453125 C 56.40625 170.613281 53.710938 184.414062 58.761719 196.347656 C 63.808594 208.28125 75.585938 215.960938 88.539062 215.765625 L 154.085938 215.765625 L 154.085938 281.003906 C 153.898438 292.488281 159.917969 303.183594 169.835938 308.984375 C 179.753906 314.785156 192.027344 314.785156 201.945312 308.992188 C 211.863281 303.199219 217.890625 292.503906 217.707031 281.019531 L 217.707031 215.765625 L 283.894531 215.765625 C 295.296875 215.820312 305.855469 209.769531 311.574219 199.90625 C 317.292969 190.042969 317.296875 177.871094 311.582031 168.007812 C 305.871094 158.140625 295.3125 152.085938 283.910156 152.132812 L 217.703125 152.132812 L 217.703125 85.640625 C 217.820312 77.042969 214.453125 68.765625 208.367188 62.6875 C 202.28125 56.613281 193.996094 53.261719 185.398438 53.390625 Z M 185.398438 53.390625 "/> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
width="375px"
height="375px"
viewBox="0 0 375 375"
version="1.1"
>
<g id="surface1">
<path
style="fill-rule:nonzero;fill:rgb(21.568628%,83.92157%,28.627452%);fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(37.64706%,37.64706%,37.64706%);stroke-opacity:1;stroke-miterlimit:4;"
d="M 98 49.021438 C 98 76.083729 76.062292 98.021438 49 98.021438 C 21.937708 98.021438 0 76.083729 0 49.021438 C 0 21.959146 21.937708 0.0214375 49 0.0214375 C 76.062292 0.0214375 98 21.959146 98 49.021438 Z M 98 49.021438 "
transform="matrix(3.826531,0,0,3.826531,0,0)"
/>
<path
style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;"
d="M 185.398438 53.390625 C 176.808594 53.523438 168.636719 57.125 162.738281 63.378906 C 157.074219 69.394531 153.96875 77.378906 154.085938 85.640625 L 154.085938 152.132812 L 88.527344 152.132812 C 79.929688 152.011719 71.644531 155.371094 65.566406 161.453125 C 56.40625 170.613281 53.710938 184.414062 58.761719 196.347656 C 63.808594 208.28125 75.585938 215.960938 88.539062 215.765625 L 154.085938 215.765625 L 154.085938 281.003906 C 153.898438 292.488281 159.917969 303.183594 169.835938 308.984375 C 179.753906 314.785156 192.027344 314.785156 201.945312 308.992188 C 211.863281 303.199219 217.890625 292.503906 217.707031 281.019531 L 217.707031 215.765625 L 283.894531 215.765625 C 295.296875 215.820312 305.855469 209.769531 311.574219 199.90625 C 317.292969 190.042969 317.296875 177.871094 311.582031 168.007812 C 305.871094 158.140625 295.3125 152.085938 283.910156 152.132812 L 217.703125 152.132812 L 217.703125 85.640625 C 217.820312 77.042969 214.453125 68.765625 208.367188 62.6875 C 202.28125 56.613281 193.996094 53.261719 185.398438 53.390625 Z M 185.398438 53.390625 "
/>
</g>
</svg>

View file

@ -1,4 +1,24 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="303px" height="374px" viewBox="0 0 303 374" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(43.921569%,77.254903%,28.627452%);fill-opacity:1;" d="M 151.5 0 C 67.828125 0 0 67.808594 0 151.453125 C 0.0742188 203.539062 26.914062 251.933594 71.0625 279.589844 C 83.773438 287.726562 98.976562 305.320312 111.8125 321.363281 C 125.679688 338.699219 133.386719 374.292969 150.203125 374.5625 C 167.015625 374.292969 174.730469 338.699219 188.597656 321.363281 C 199.703125 307.480469 211.496094 292.414062 224.496094 283.984375 C 272.859375 257.398438 302.933594 206.628906 303 151.453125 C 303 67.808594 235.171875 0 151.5 0 Z M 151.5 0 "/> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
width="303px"
height="374px"
viewBox="0 0 303 374"
version="1.1"
>
<g id="surface1">
<path
style=" stroke:none;fill-rule:nonzero;fill:rgb(43.921569%,77.254903%,28.627452%);fill-opacity:1;"
d="M 151.5 0 C 67.828125 0 0 67.808594 0 151.453125 C 0.0742188 203.539062 26.914062 251.933594 71.0625 279.589844 C 83.773438 287.726562 98.976562 305.320312 111.8125 321.363281 C 125.679688 338.699219 133.386719 374.292969 150.203125 374.5625 C 167.015625 374.292969 174.730469 338.699219 188.597656 321.363281 C 199.703125 307.480469 211.496094 292.414062 224.496094 283.984375 C 272.859375 257.398438 302.933594 206.628906 303 151.453125 C 303 67.808594 235.171875 0 151.5 0 Z M 151.5 0 "
/>
</g>
</svg>

View file

@ -1,4 +1,30 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:5.291667;stroke-linecap:round;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 14.287499 23.618748 L 4.143209 13.229167 L 14.287499 2.871556 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,0)"/> <path style="fill: none !important;stroke-width:3.96875;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 5.532271 13.229167 C 12.346946 13.21704 23.467714 13.190031 23.8125 13.200504 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,0)"/> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
width="375px"
height="375px"
viewBox="0 0 375 375"
version="1.1"
>
<g id="surface1">
<path
style="fill: none !important;stroke-width:5.291667;stroke-linecap:round;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;"
d="M 14.287499 23.618748 L 4.143209 13.229167 L 14.287499 2.871556 "
transform="matrix(14.173228,0,0,14.173228,0.0000135166,0)"
/>
<path
style="fill: none !important;stroke-width:3.96875;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;"
d="M 5.532271 13.229167 C 12.346946 13.21704 23.467714 13.190031 23.8125 13.200504 "
transform="matrix(14.173228,0,0,14.173228,0.0000135166,0)"
/>
</g>
</svg>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,24 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="268px" height="373px" viewBox="0 0 268 373" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:{color};fill-opacity:1;" d="M 88.972656 57.019531 C 69.667969 77.699219 74.996094 110.734375 74.996094 110.734375 C 74.996094 110.734375 94.699219 134.046875 133.414062 134.046875 C 172.128906 134.046875 191.84375 110.734375 191.84375 110.734375 C 191.84375 110.734375 197.09375 78.144531 178.199219 57.4375 C 190.019531 50.871094 196.980469 41.378906 194.105469 34.921875 C 190.839844 27.648438 176.441406 27 161.882812 33.476562 C 156.472656 35.878906 151.863281 38.929688 148.28125 42.175781 C 143.742188 41.355469 138.925781 40.796875 133.414062 40.796875 C 128.28125 40.796875 123.714844 41.285156 119.414062 41.980469 C 115.886719 38.792969 111.359375 35.835938 106.074219 33.476562 C 91.515625 27.023438 77.09375 27.671875 73.851562 34.921875 C 71.023438 41.242188 77.609375 50.472656 88.972656 57.019531 Z M 235.433594 207.535156 C 232.417969 206.898438 229.542969 206.535156 226.761719 206.261719 C 226.761719 205.488281 226.898438 204.757812 226.898438 203.960938 C 226.898438 191.726562 225.164062 180.046875 222.355469 168.949219 C 228.359375 169.460938 236.003906 168.082031 243.738281 164.65625 C 258.296875 158.179688 267.472656 147.035156 264.230469 139.808594 C 260.992188 132.535156 246.566406 131.886719 232.007812 138.363281 C 225.207031 141.390625 219.664062 145.453125 215.945312 149.621094 C 213.113281 142.972656 209.917969 136.585938 206.152344 130.78125 C 195.132812 139.945312 174.273438 153.625 145.15625 156.664062 L 145.15625 273.875 C 145.15625 273.875 145.0625 285.53125 133.460938 285.53125 C 121.867188 285.53125 121.777344 273.875 121.777344 273.875 L 121.777344 156.710938 C 92.636719 153.671875 71.765625 139.964844 60.765625 130.824219 C 57.160156 136.402344 54.058594 142.480469 51.296875 148.800781 C 47.542969 144.929688 42.304688 141.207031 35.972656 138.382812 C 21.414062 131.929688 6.992188 132.578125 3.75 139.828125 C 0.5 147.082031 9.683594 158.203125 24.242188 164.679688 C 31.488281 167.902344 38.675781 169.347656 44.496094 169.085938 C 41.699219 180.160156 39.941406 191.792969 39.941406 203.984375 C 39.941406 204.78125 40.082031 205.535156 40.101562 206.351562 C 37.648438 206.625 35.105469 206.992188 32.515625 207.535156 C 13.539062 211.453125 -0.996094 221.242188 0.078125 229.324219 C 1.148438 237.453125 17.421875 240.796875 36.441406 236.859375 C 38.917969 236.359375 41.347656 235.722656 43.664062 235.015625 C 47.007812 249.882812 52.359375 263.675781 59.761719 275.5625 C 55.371094 277.769531 50.804688 281.023438 46.605469 285.257812 C 34.96875 296.871094 30.246094 310.984375 36.0625 316.789062 C 41.882812 322.597656 56.019531 317.882812 67.660156 306.296875 C 71.070312 302.878906 73.808594 299.285156 75.929688 295.730469 C 91.824219 311.257812 111.734375 320.546875 133.460938 320.546875 C 155.492188 320.546875 175.734375 310.984375 191.707031 295.070312 C 193.855469 298.828125 196.730469 302.652344 200.335938 306.25 C 211.949219 317.859375 226.121094 322.574219 231.941406 316.769531 C 237.757812 310.960938 233.035156 296.871094 221.398438 285.257812 C 216.902344 280.75 212.019531 277.335938 207.363281 275.082031 C 214.710938 263.246094 220.003906 249.449219 223.316406 234.628906 C 225.9375 235.445312 228.675781 236.222656 231.550781 236.835938 C 250.5625 240.773438 266.832031 237.40625 267.925781 229.300781 C 268.953125 221.242188 254.417969 211.453125 235.433594 207.535156 Z M 235.433594 207.535156 "/> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
width="268px"
height="373px"
viewBox="0 0 268 373"
version="1.1"
>
<g id="surface1">
<path
style=" stroke:none;fill-rule:nonzero;fill:{color};fill-opacity:1;"
d="M 88.972656 57.019531 C 69.667969 77.699219 74.996094 110.734375 74.996094 110.734375 C 74.996094 110.734375 94.699219 134.046875 133.414062 134.046875 C 172.128906 134.046875 191.84375 110.734375 191.84375 110.734375 C 191.84375 110.734375 197.09375 78.144531 178.199219 57.4375 C 190.019531 50.871094 196.980469 41.378906 194.105469 34.921875 C 190.839844 27.648438 176.441406 27 161.882812 33.476562 C 156.472656 35.878906 151.863281 38.929688 148.28125 42.175781 C 143.742188 41.355469 138.925781 40.796875 133.414062 40.796875 C 128.28125 40.796875 123.714844 41.285156 119.414062 41.980469 C 115.886719 38.792969 111.359375 35.835938 106.074219 33.476562 C 91.515625 27.023438 77.09375 27.671875 73.851562 34.921875 C 71.023438 41.242188 77.609375 50.472656 88.972656 57.019531 Z M 235.433594 207.535156 C 232.417969 206.898438 229.542969 206.535156 226.761719 206.261719 C 226.761719 205.488281 226.898438 204.757812 226.898438 203.960938 C 226.898438 191.726562 225.164062 180.046875 222.355469 168.949219 C 228.359375 169.460938 236.003906 168.082031 243.738281 164.65625 C 258.296875 158.179688 267.472656 147.035156 264.230469 139.808594 C 260.992188 132.535156 246.566406 131.886719 232.007812 138.363281 C 225.207031 141.390625 219.664062 145.453125 215.945312 149.621094 C 213.113281 142.972656 209.917969 136.585938 206.152344 130.78125 C 195.132812 139.945312 174.273438 153.625 145.15625 156.664062 L 145.15625 273.875 C 145.15625 273.875 145.0625 285.53125 133.460938 285.53125 C 121.867188 285.53125 121.777344 273.875 121.777344 273.875 L 121.777344 156.710938 C 92.636719 153.671875 71.765625 139.964844 60.765625 130.824219 C 57.160156 136.402344 54.058594 142.480469 51.296875 148.800781 C 47.542969 144.929688 42.304688 141.207031 35.972656 138.382812 C 21.414062 131.929688 6.992188 132.578125 3.75 139.828125 C 0.5 147.082031 9.683594 158.203125 24.242188 164.679688 C 31.488281 167.902344 38.675781 169.347656 44.496094 169.085938 C 41.699219 180.160156 39.941406 191.792969 39.941406 203.984375 C 39.941406 204.78125 40.082031 205.535156 40.101562 206.351562 C 37.648438 206.625 35.105469 206.992188 32.515625 207.535156 C 13.539062 211.453125 -0.996094 221.242188 0.078125 229.324219 C 1.148438 237.453125 17.421875 240.796875 36.441406 236.859375 C 38.917969 236.359375 41.347656 235.722656 43.664062 235.015625 C 47.007812 249.882812 52.359375 263.675781 59.761719 275.5625 C 55.371094 277.769531 50.804688 281.023438 46.605469 285.257812 C 34.96875 296.871094 30.246094 310.984375 36.0625 316.789062 C 41.882812 322.597656 56.019531 317.882812 67.660156 306.296875 C 71.070312 302.878906 73.808594 299.285156 75.929688 295.730469 C 91.824219 311.257812 111.734375 320.546875 133.460938 320.546875 C 155.492188 320.546875 175.734375 310.984375 191.707031 295.070312 C 193.855469 298.828125 196.730469 302.652344 200.335938 306.25 C 211.949219 317.859375 226.121094 322.574219 231.941406 316.769531 C 237.757812 310.960938 233.035156 296.871094 221.398438 285.257812 C 216.902344 280.75 212.019531 277.335938 207.363281 275.082031 C 214.710938 263.246094 220.003906 249.449219 223.316406 234.628906 C 225.9375 235.445312 228.675781 236.222656 231.550781 236.835938 C 250.5625 240.773438 266.832031 237.40625 267.925781 229.300781 C 268.953125 221.242188 254.417969 211.453125 235.433594 207.535156 Z M 235.433594 207.535156 "
/>
</g>
</svg>

View file

@ -1,4 +1,38 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:{color};fill-opacity:1;" d="M 169.460938 135.585938 C 184.714844 135.585938 197.761719 141.003906 208.59375 151.835938 C 219.425781 162.667969 224.84375 175.714844 224.84375 190.972656 C 224.84375 206.226562 219.425781 219.273438 208.59375 230.105469 C 197.761719 240.9375 184.714844 246.355469 169.460938 246.355469 C 154.203125 246.355469 141.160156 240.9375 130.324219 230.105469 C 119.492188 219.273438 114.074219 206.226562 114.074219 190.972656 C 114.074219 175.714844 119.492188 162.667969 130.324219 151.835938 C 141.160156 141.003906 154.203125 135.585938 169.460938 135.585938 M 322.921875 74.816406 C 336.511719 74.816406 348.113281 79.625 357.730469 89.242188 C 367.34375 98.855469 372.152344 110.457031 372.152344 124.046875 L 372.152344 296.355469 C 372.152344 309.945312 367.34375 321.546875 357.730469 331.164062 C 348.113281 340.777344 336.511719 345.585938 322.921875 345.585938 L 52.152344 345.585938 C 38.5625 345.585938 26.960938 340.777344 17.34375 331.164062 C 7.730469 321.546875 2.921875 309.945312 2.921875 296.355469 L 2.921875 124.046875 C 2.921875 110.457031 7.730469 98.855469 17.34375 89.242188 C 26.960938 79.625 38.5625 74.816406 52.152344 74.816406 L 77.152344 74.816406 L 86.960938 48.664062 C 89.394531 42.382812 93.851562 36.964844 100.324219 32.414062 C 106.800781 27.863281 113.433594 25.585938 120.230469 25.585938 L 218.691406 25.585938 C 225.484375 25.585938 232.121094 27.863281 238.59375 32.414062 C 245.070312 36.964844 249.523438 42.382812 251.960938 48.664062 L 261.765625 74.816406 L 322.921875 74.816406 M 169.460938 277.125 C 193.175781 277.125 213.464844 268.695312 230.324219 251.835938 C 247.183594 234.976562 255.613281 214.6875 255.613281 190.972656 C 255.613281 167.253906 247.183594 146.964844 230.324219 130.105469 C 213.464844 113.246094 193.175781 104.816406 169.460938 104.816406 C 145.742188 104.816406 125.453125 113.246094 108.59375 130.105469 C 91.734375 146.964844 83.304688 167.253906 83.304688 190.972656 C 83.304688 214.6875 91.734375 234.976562 108.59375 251.835938 C 125.453125 268.695312 145.742188 277.125 169.460938 277.125 "/> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(49.411765%,73.725492%,43.529412%);fill-opacity:1;" d="M 374.332031 308.261719 C 374.332031 343.875 345.464844 372.746094 309.851562 372.746094 C 274.238281 372.746094 245.371094 343.875 245.371094 308.261719 C 245.371094 272.652344 274.238281 243.78125 309.851562 243.78125 C 345.464844 243.78125 374.332031 272.652344 374.332031 308.261719 Z M 374.332031 308.261719 "/> <path style="fill: none !important;stroke-width:95.518036;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 1154.783124 1044.338782 L 1543.909686 1044.338782 " transform="matrix(0.192308,0,0,0.192308,49.973197,107.396088)"/> <path style="fill: none !important;stroke-width:95.518036;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 1349.925311 849.359094 L 1349.925311 1238.505969 " transform="matrix(0.192308,0,0,0.192308,49.973197,107.396088)"/> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
width="375px"
height="375px"
viewBox="0 0 375 375"
version="1.1"
>
<g id="surface1">
<path
style=" stroke:none;fill-rule:nonzero;fill:{color};fill-opacity:1;"
d="M 169.460938 135.585938 C 184.714844 135.585938 197.761719 141.003906 208.59375 151.835938 C 219.425781 162.667969 224.84375 175.714844 224.84375 190.972656 C 224.84375 206.226562 219.425781 219.273438 208.59375 230.105469 C 197.761719 240.9375 184.714844 246.355469 169.460938 246.355469 C 154.203125 246.355469 141.160156 240.9375 130.324219 230.105469 C 119.492188 219.273438 114.074219 206.226562 114.074219 190.972656 C 114.074219 175.714844 119.492188 162.667969 130.324219 151.835938 C 141.160156 141.003906 154.203125 135.585938 169.460938 135.585938 M 322.921875 74.816406 C 336.511719 74.816406 348.113281 79.625 357.730469 89.242188 C 367.34375 98.855469 372.152344 110.457031 372.152344 124.046875 L 372.152344 296.355469 C 372.152344 309.945312 367.34375 321.546875 357.730469 331.164062 C 348.113281 340.777344 336.511719 345.585938 322.921875 345.585938 L 52.152344 345.585938 C 38.5625 345.585938 26.960938 340.777344 17.34375 331.164062 C 7.730469 321.546875 2.921875 309.945312 2.921875 296.355469 L 2.921875 124.046875 C 2.921875 110.457031 7.730469 98.855469 17.34375 89.242188 C 26.960938 79.625 38.5625 74.816406 52.152344 74.816406 L 77.152344 74.816406 L 86.960938 48.664062 C 89.394531 42.382812 93.851562 36.964844 100.324219 32.414062 C 106.800781 27.863281 113.433594 25.585938 120.230469 25.585938 L 218.691406 25.585938 C 225.484375 25.585938 232.121094 27.863281 238.59375 32.414062 C 245.070312 36.964844 249.523438 42.382812 251.960938 48.664062 L 261.765625 74.816406 L 322.921875 74.816406 M 169.460938 277.125 C 193.175781 277.125 213.464844 268.695312 230.324219 251.835938 C 247.183594 234.976562 255.613281 214.6875 255.613281 190.972656 C 255.613281 167.253906 247.183594 146.964844 230.324219 130.105469 C 213.464844 113.246094 193.175781 104.816406 169.460938 104.816406 C 145.742188 104.816406 125.453125 113.246094 108.59375 130.105469 C 91.734375 146.964844 83.304688 167.253906 83.304688 190.972656 C 83.304688 214.6875 91.734375 234.976562 108.59375 251.835938 C 125.453125 268.695312 145.742188 277.125 169.460938 277.125 "
/>
<path
style=" stroke:none;fill-rule:nonzero;fill:rgb(49.411765%,73.725492%,43.529412%);fill-opacity:1;"
d="M 374.332031 308.261719 C 374.332031 343.875 345.464844 372.746094 309.851562 372.746094 C 274.238281 372.746094 245.371094 343.875 245.371094 308.261719 C 245.371094 272.652344 274.238281 243.78125 309.851562 243.78125 C 345.464844 243.78125 374.332031 272.652344 374.332031 308.261719 Z M 374.332031 308.261719 "
/>
<path
style="fill: none !important;stroke-width:95.518036;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;"
d="M 1154.783124 1044.338782 L 1543.909686 1044.338782 "
transform="matrix(0.192308,0,0,0.192308,49.973197,107.396088)"
/>
<path
style="fill: none !important;stroke-width:95.518036;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;"
d="M 1349.925311 849.359094 L 1349.925311 1238.505969 "
transform="matrix(0.192308,0,0,0.192308,49.973197,107.396088)"
/>
</g>
</svg>

View file

@ -1,4 +1,25 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="374px" height="259px" viewBox="0 0 374 259" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 2.999896 7.285624 L 10.826182 14.99991 L 23.000104 3.00009 " transform="matrix(14.384615,0,0,14.388889,0,0)"/> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
width="374px"
height="259px"
viewBox="0 0 374 259"
version="1.1"
>
<g id="surface1">
<path
style="fill: none !important;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;"
d="M 2.999896 7.285624 L 10.826182 14.99991 L 23.000104 3.00009 "
transform="matrix(14.384615,0,0,14.388889,0,0)"
/>
</g>
</svg>

View file

@ -1,4 +1,25 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill:{color};" class="selectable" d="M 375 187.5 C 375 291.054688 291.054688 375 187.5 375 C 83.945312 375 0 291.054688 0 187.5 C 0 83.945312 83.945312 0 187.5 0 C 291.054688 0 375 83.945312 375 187.5 Z M 375 187.5 "/> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
width="375px"
height="375px"
viewBox="0 0 375 375"
version="1.1"
>
<g id="surface1">
<path
style="fill:{color};"
class="selectable"
d="M 375 187.5 C 375 291.054688 291.054688 375 187.5 375 C 83.945312 375 0 291.054688 0 187.5 C 0 83.945312 83.945312 0 187.5 0 C 291.054688 0 375 83.945312 375 187.5 Z M 375 187.5 "
/>
</g>
</svg>

View file

@ -1,4 +1,30 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:9;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 46 55.932292 L 66.551042 55.932292 " transform="matrix(3.75,0,0,3.75,0,0)"/> <path style="fill: none !important;stroke-width:9;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 46 55.534375 L 46 27.729167 " transform="matrix(3.75,0,0,3.75,0,0)"/> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
width="375px"
height="375px"
viewBox="0 0 375 375"
version="1.1"
>
<g id="surface1">
<path
style="fill: none !important;stroke-width:9;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;"
d="M 46 55.932292 L 66.551042 55.932292 "
transform="matrix(3.75,0,0,3.75,0,0)"
/>
<path
style="fill: none !important;stroke-width:9;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;"
d="M 46 55.534375 L 46 27.729167 "
transform="matrix(3.75,0,0,3.75,0,0)"
/>
</g>
</svg>

View file

@ -1,4 +1,30 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:6.012842;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 23.165924 293.603402 L 3.541282 273.978759 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:6.012921;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 23.195414 273.884226 L 3.571047 293.508593 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
width="375px"
height="375px"
viewBox="0 0 375 375"
version="1.1"
>
<g id="surface1">
<path
style="fill: none !important;stroke-width:6.012842;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;"
d="M 23.165924 293.603402 L 3.541282 273.978759 "
transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"
/>
<path
style="fill: none !important;stroke-width:6.012921;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;"
d="M 23.195414 273.884226 L 3.571047 293.508593 "
transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"
/>
</g>
</svg>

View file

@ -1,4 +1,35 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<!-- Created with Inkscape (http://www.inkscape.org/) --> <svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown width="1124.975mm" height="1111.9373mm" viewBox="0 0 1124.975 1111.9373" version="1.1" id="svg5" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs2" /> <g id="layer1" transform="translate(429.38456,373.85159)" style="display:inline"> <path id="path858" d="m 465.50195,-1412.9824 c -48.13018,0 -95.14167,6.6605 -140.92968,19.3242 -517.78906,36.4545 -1004.59215,263.4542 -1364.78127,639.11132 -125.578,130.97093 -232.0356,276.80492 -318.709,432.875 l -3.0996,0.006 0.012,5.62891 c -169.1451,306.7883664 -260.6208,653.52706 -260.8652,1009.62695 v 0.0645 c 0,555.45592 220.6943,1088.26072 613.4609,1481.02732 378.0703,378.0702 885.96964,596.0875 1418.85161,611.92 18.51351,1.9864 37.20113,3.0136 56.06054,3.0136 17.25834,0 34.36078,-0.9283 51.33008,-2.5937 224.45873,-4.8504 444.64455,-45.7063 652.83597,-119.1836 -60.8675,-43.0776 -118.1478,-91.0122 -171.27933,-143.334 -121.72268,40.4323 -230.24225,90.5328 -428.68164,58.6602 l -3.38086,-1775.19732 233.78516,-0.44532 c 42.42213,-67.09791 90.54812,-130.41487 143.84375,-189.24804 l -377.98828,0.7207 -1.43946,-755.89648 634.26176,-1.38672 c 32.7782,154.928763 56.3858,319.47347 69.9629,489.41797 58.6612,-33.17515 119.6711,-62.01386 182.541,-86.28516 -13.1747,-138.65014 -32.7954,-273.7956044 -58.7852,-403.55664 l 791.918,-1.73242 c 54.2995,111.507047 97.5037,228.170813 129.2012,348.26953 72.3897,18.82425 143.1313,43.49582 211.5273,73.77148 -80.6791,-402.00209 -278.3137,-774.77273 -572.5098,-1068.96875 -363.7812,-363.78173 -847.7515,-579.57553 -1358.52731,-609.49993 -41.8967,-10.5343 -84.78727,-16.1094 -128.61524,-16.1094 z m 96.98438,204.4375 c 159.67283,49.2174 326.54513,218.8615 462.03907,516.93552 49.6393,109.20202 92.1295,232.60044 128.4531,364.44727 l -588.81053,1.28711 z m -188.97461,0.9179 1.67969,882.16411 -597.98243,1.30664 c 36.4911,-132.99204 79.25432,-257.42426 129.269536,-367.45313 133.780665,-294.30513 298.164144,-463.66612 455.992184,-515.27932 3.68603,-0.2115 7.36574,-0.4597 11.04102,-0.7383 z m 591.27148,61.1954 c 320.2851,85.8427 615.6781,254.12924 854.2344,492.68551 99.0716,99.07158 185.6177,208.20254 259.6738,324.5625 l -729.584,1.59375 c -41.2536,-159.09493 -91.7465,-308.46744 -152.5469,-442.22266 -67.1207,-147.65948 -144.9895,-275.0596 -231.7773,-376.6191 z m -1003.50195,5.9433 c -84.79247,100.5848 -161.00089,225.84047 -226.83789,370.6758 -61.29809,134.85015 -112.17438,285.51379 -153.59961,446.08594 l -720.14645,1.57422 c 67.8012,-107.37947 146.33969,-208.61822 235.49997,-301.60743 238.54174,-248.78579 538.10225,-425.81263 865.08398,-516.72853 z m 414.26953,1004.00002 1.43945,755.8418 -727.68554,1.38671 c 4.20418,-264.24481 32.77031,-520.983169 82.2207,-755.82031 z m -837.92773,1.83203 c -47.33699,237.75431 -73.46184,493.4318 -77.33789,755.75781 l -892.42186,1.70117 c 10.0141,-264.11069 74.8439,-521.07351 188.0937,-755.75 z m 839.72656,942.98437 1.3457,707.00198 -646.08984,1.414 c -46.71986,-220.2353 -75.01919,-459.8106 -82.07617,-707.03121 z m -915.85156,1.74415 c 6.57514,245.41033 32.61831,484.16193 77.38867,707.09573 l -784.53902,1.7148 c -105.8005,-220.1735 -168.8074,-460.0874 -184.1446,-707.11327 z m 917.55859,894.23433 1.68359,884.2715 C 217.38802,2544.4462 45.439072,2373.9426 -93.521484,2068.2422 -142.93255,1959.5424 -185.25941,1836.7732 -221.48047,1705.6211 Z m -796.66211,1.7422 c 41.17164,158.3984 91.48351,307.1603 152.04883,440.3985 69.28935,152.4302 150.07483,283.1451 240.259765,386.2558 C -344.1327,2446.5457 -638.16035,2278.6776 -875.7832,2041.0547 -977.36504,1939.4729 -1065.801,1827.3298 -1141.0586,1707.6328 Z" transform="scale(0.26458333)" /> <path id="path928" d="" /> <path id="path890" d="" /> <path id="path3123" d="m 500.42418,99.52416 c -162.9348,1.72512 -108.06353,223.75011 -69.65465,274.06343 l 1.09709,35.29034 c -176.038,13.83721 -191.80907,75.90897 -198.43798,158.82719 -2.02223,25.29521 3.89762,50.2628 9.81667,80.72646 97.56502,-0.71585 177.50757,-0.62612 275.07185,-0.49796 84.27329,-45.47436 147.33813,-122.20106 175.63579,-213.68411 -28.16643,-12.43076 -66.9608,-21.14889 -120.68876,-25.37209 l 1.09762,-35.29036 C 613.0731,322.8775 663.35897,97.79884 500.42418,99.52416 Z" /> </g> </svg>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
width="1124.975mm"
height="1111.9373mm"
viewBox="0 0 1124.975 1111.9373"
version="1.1"
id="svg5"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
>
<defs id="defs2" />
<g id="layer1" transform="translate(429.38456,373.85159)" style="display:inline">
<path
id="path858"
d="m 465.50195,-1412.9824 c -48.13018,0 -95.14167,6.6605 -140.92968,19.3242 -517.78906,36.4545 -1004.59215,263.4542 -1364.78127,639.11132 -125.578,130.97093 -232.0356,276.80492 -318.709,432.875 l -3.0996,0.006 0.012,5.62891 c -169.1451,306.7883664 -260.6208,653.52706 -260.8652,1009.62695 v 0.0645 c 0,555.45592 220.6943,1088.26072 613.4609,1481.02732 378.0703,378.0702 885.96964,596.0875 1418.85161,611.92 18.51351,1.9864 37.20113,3.0136 56.06054,3.0136 17.25834,0 34.36078,-0.9283 51.33008,-2.5937 224.45873,-4.8504 444.64455,-45.7063 652.83597,-119.1836 -60.8675,-43.0776 -118.1478,-91.0122 -171.27933,-143.334 -121.72268,40.4323 -230.24225,90.5328 -428.68164,58.6602 l -3.38086,-1775.19732 233.78516,-0.44532 c 42.42213,-67.09791 90.54812,-130.41487 143.84375,-189.24804 l -377.98828,0.7207 -1.43946,-755.89648 634.26176,-1.38672 c 32.7782,154.928763 56.3858,319.47347 69.9629,489.41797 58.6612,-33.17515 119.6711,-62.01386 182.541,-86.28516 -13.1747,-138.65014 -32.7954,-273.7956044 -58.7852,-403.55664 l 791.918,-1.73242 c 54.2995,111.507047 97.5037,228.170813 129.2012,348.26953 72.3897,18.82425 143.1313,43.49582 211.5273,73.77148 -80.6791,-402.00209 -278.3137,-774.77273 -572.5098,-1068.96875 -363.7812,-363.78173 -847.7515,-579.57553 -1358.52731,-609.49993 -41.8967,-10.5343 -84.78727,-16.1094 -128.61524,-16.1094 z m 96.98438,204.4375 c 159.67283,49.2174 326.54513,218.8615 462.03907,516.93552 49.6393,109.20202 92.1295,232.60044 128.4531,364.44727 l -588.81053,1.28711 z m -188.97461,0.9179 1.67969,882.16411 -597.98243,1.30664 c 36.4911,-132.99204 79.25432,-257.42426 129.269536,-367.45313 133.780665,-294.30513 298.164144,-463.66612 455.992184,-515.27932 3.68603,-0.2115 7.36574,-0.4597 11.04102,-0.7383 z m 591.27148,61.1954 c 320.2851,85.8427 615.6781,254.12924 854.2344,492.68551 99.0716,99.07158 185.6177,208.20254 259.6738,324.5625 l -729.584,1.59375 c -41.2536,-159.09493 -91.7465,-308.46744 -152.5469,-442.22266 -67.1207,-147.65948 -144.9895,-275.0596 -231.7773,-376.6191 z m -1003.50195,5.9433 c -84.79247,100.5848 -161.00089,225.84047 -226.83789,370.6758 -61.29809,134.85015 -112.17438,285.51379 -153.59961,446.08594 l -720.14645,1.57422 c 67.8012,-107.37947 146.33969,-208.61822 235.49997,-301.60743 238.54174,-248.78579 538.10225,-425.81263 865.08398,-516.72853 z m 414.26953,1004.00002 1.43945,755.8418 -727.68554,1.38671 c 4.20418,-264.24481 32.77031,-520.983169 82.2207,-755.82031 z m -837.92773,1.83203 c -47.33699,237.75431 -73.46184,493.4318 -77.33789,755.75781 l -892.42186,1.70117 c 10.0141,-264.11069 74.8439,-521.07351 188.0937,-755.75 z m 839.72656,942.98437 1.3457,707.00198 -646.08984,1.414 c -46.71986,-220.2353 -75.01919,-459.8106 -82.07617,-707.03121 z m -915.85156,1.74415 c 6.57514,245.41033 32.61831,484.16193 77.38867,707.09573 l -784.53902,1.7148 c -105.8005,-220.1735 -168.8074,-460.0874 -184.1446,-707.11327 z m 917.55859,894.23433 1.68359,884.2715 C 217.38802,2544.4462 45.439072,2373.9426 -93.521484,2068.2422 -142.93255,1959.5424 -185.25941,1836.7732 -221.48047,1705.6211 Z m -796.66211,1.7422 c 41.17164,158.3984 91.48351,307.1603 152.04883,440.3985 69.28935,152.4302 150.07483,283.1451 240.259765,386.2558 C -344.1327,2446.5457 -638.16035,2278.6776 -875.7832,2041.0547 -977.36504,1939.4729 -1065.801,1827.3298 -1141.0586,1707.6328 Z"
transform="scale(0.26458333)"
/>
<path id="path928" d="" />
<path id="path890" d="" />
<path
id="path3123"
d="m 500.42418,99.52416 c -162.9348,1.72512 -108.06353,223.75011 -69.65465,274.06343 l 1.09709,35.29034 c -176.038,13.83721 -191.80907,75.90897 -198.43798,158.82719 -2.02223,25.29521 3.89762,50.2628 9.81667,80.72646 97.56502,-0.71585 177.50757,-0.62612 275.07185,-0.49796 84.27329,-45.47436 147.33813,-122.20106 175.63579,-213.68411 -28.16643,-12.43076 -66.9608,-21.14889 -120.68876,-25.37209 l 1.09762,-35.29036 C 613.0731,322.8775 663.35897,97.79884 500.42418,99.52416 Z"
/>
</g>
</svg>

View file

@ -1,4 +1,26 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#F4900C" cx="18" cy="18" r="18"/><circle fill="#FFD983" cx="18" cy="18" r="14.5"/><circle fill="#F5F8FA" cx="18" cy="18" r="13"/><path fill="#CCD6DD" d="M18 8l1.531 6.304 5.54-3.375-3.375 5.54L28 18l-6.304 1.531 3.375 5.54-5.54-3.375L18 28l-1.531-6.304-5.54 3.375 3.375-5.54L8 18l6.304-1.531-3.375-5.54 5.54 3.375z"/><path fill="#292F33" d="M17.343 20.748l8.777 5.381-5.379-8.778z"/><path fill="#DD2E44" d="M18.657 15.267L9.879 9.886l5.38 8.779z"/><circle fill="#8899A6" cx="18" cy="18.008" r="3.055"/><circle fill="#F5F8FA" cx="18" cy="18.008" r="1.648"/></svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 36 36"
>
<circle fill="#F4900C" cx="18" cy="18" r="18" />
<circle fill="#FFD983" cx="18" cy="18" r="14.5" />
<circle fill="#F5F8FA" cx="18" cy="18" r="13" />
<path
fill="#CCD6DD"
d="M18 8l1.531 6.304 5.54-3.375-3.375 5.54L28 18l-6.304 1.531 3.375 5.54-5.54-3.375L18 28l-1.531-6.304-5.54 3.375 3.375-5.54L8 18l6.304-1.531-3.375-5.54 5.54 3.375z"
/>
<path fill="#292F33" d="M17.343 20.748l8.777 5.381-5.379-8.778z" />
<path fill="#DD2E44" d="M18.657 15.267L9.879 9.886l5.38 8.779z" />
<circle fill="#8899A6" cx="18" cy="18.008" r="3.055" />
<circle fill="#F5F8FA" cx="18" cy="18.008" r="1.648" />
</svg>

View file

@ -1,4 +1,49 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown width="157.33984" height="157.33984" viewBox="0 0 157.33984 157.33984" version="1.1" id="svg9" sodipodi:docname="confirm.svg" inkscape:version="1.1.2 (1:1.1+202202050950+0a00cf5339)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs13" /> <sodipodi:namedview id="namedview11" pagecolor="#505050" bordercolor="#eeeeee" borderopacity="1" inkscape:pageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" showgrid="false" inkscape:zoom="2.312" inkscape:cx="-18.598616" inkscape:cy="57.093426" inkscape:current-layer="svg9" /> <path style="fill:#35d447;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 157.33984,78.66796 c 0,43.44922 -35.21875,78.67188 -78.66796,78.67188 C 35.22266,157.33984 0,122.11718 0,78.66796 0,35.22265 35.22266,0 78.67188,0 c 43.44921,0 78.66796,35.22265 78.66796,78.66796 z m 0,0" id="path4" /> <path style="fill: none !important;stroke:#ffffff;stroke-width:19.7495;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" d="m 37.69921,75.49609 35.55078,39.5 47.39844,-63.19922" id="path6" /> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
width="157.33984"
height="157.33984"
viewBox="0 0 157.33984 157.33984"
version="1.1"
id="svg9"
sodipodi:docname="confirm.svg"
inkscape:version="1.1.2 (1:1.1+202202050950+0a00cf5339)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
>
<defs id="defs13" />
<sodipodi:namedview
id="namedview11"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="2.312"
inkscape:cx="-18.598616"
inkscape:cy="57.093426"
inkscape:current-layer="svg9"
/>
<path
style="fill:#35d447;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 157.33984,78.66796 c 0,43.44922 -35.21875,78.67188 -78.66796,78.67188 C 35.22266,157.33984 0,122.11718 0,78.66796 0,35.22265 35.22266,0 78.67188,0 c 43.44921,0 78.66796,35.22265 78.66796,78.66796 z m 0,0"
id="path4"
/>
<path
style="fill: none !important;stroke:#ffffff;stroke-width:19.7495;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
d="m 37.69921,75.49609 35.55078,39.5 47.39844,-63.19922"
id="path6"
/>
</svg>

View file

@ -1,4 +1,51 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown width="375px" height="375px" viewBox="0 0 375 375" version="1.1" id="svg5" sodipodi:docname="copyright.svg" inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs9" /> <sodipodi:namedview id="namedview7" pagecolor="#505050" bordercolor="#eeeeee" borderopacity="1" inkscape:pageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" showgrid="false" inkscape:zoom="2.4012481" inkscape:cx="194.06574" inkscape:cy="30.192632" inkscape:window-width="1920" inkscape:window-height="995" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg5" /> <g id="surface1" transform="matrix(1.2644961,0,0,1.2644961,-49.593016,-49.593016)"> <path style="fill:{color};fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 159.26562,170.73437 c 0.73438,-4.85156 2.35157,-9.11718 4.41016,-12.79296 2.0625,-3.67579 5,-6.76172 8.67969,-9.11719 3.52734,-2.20313 7.9375,-3.23438 13.3789,-3.37891 3.38282,0.14453 6.47266,0.73438 9.26563,1.91016 2.94141,1.32422 5.58594,3.08594 7.64453,5.29297 2.05859,2.20703 3.67969,4.85156 5,7.79297 1.32422,2.9414 1.91406,6.17578 2.05859,9.41406 h 26.32422 c -0.29297,-6.91406 -1.61718,-13.23438 -4.11718,-18.97266 -2.5,-5.73437 -5.88282,-10.73437 -10.29297,-14.85156 -4.41407,-4.11719 -9.70703,-7.35156 -15.88282,-9.70312 -6.17578,-2.35547 -12.9414,-3.38282 -20.4414,-3.38282 -9.5586,0 -17.9375,1.61719 -24.9961,5 -7.05859,3.38281 -12.9414,7.79297 -17.64843,13.52735 -4.70313,5.73437 -8.23438,12.35156 -10.44141,20 -2.20312,7.64453 -3.52734,15.58593 -3.52734,24.11718 v 3.96875 c 0,8.52735 1.17578,16.46875 3.38281,24.11719 2.20312,7.64453 5.73437,14.26172 10.44141,19.85156 4.70312,5.58594 10.58593,10.14453 17.64453,13.38282 7.05859,3.23437 15.4414,5 25,5 6.91015,0 13.3789,-1.17969 19.41015,-3.38282 6.02735,-2.20703 11.32422,-5.29687 15.87891,-9.26562 4.55859,-3.96875 8.23828,-8.52735 10.88281,-13.82422 2.64844,-5.29297 4.26563,-10.87891 4.41406,-16.91016 h -26.32421 c -0.14454,3.08985 -0.88282,5.88282 -2.20704,8.53125 -1.32031,2.64453 -3.08593,4.85157 -5.29296,6.76172 -2.20313,1.91406 -4.70313,3.38281 -7.64454,4.41406 -2.79687,1.02735 -5.73437,1.32032 -8.82421,1.46875 -5.29297,-0.14843 -9.70704,-1.17578 -13.08594,-3.38281 -3.67969,-2.35156 -6.61719,-5.4414 -8.67969,-9.11719 -2.05859,-3.67578 -3.67578,-8.08593 -4.41016,-12.9375 -0.73437,-4.85546 -1.17578,-9.85546 -1.17578,-14.70703 v -3.96875 c 0,-5.14843 0.44141,-10 1.17578,-14.85547 z M 187.5,40.449219 c -81.17187,0 -147.050781,65.878911 -147.050781,147.050781 0,81.17187 65.878911,147.05078 147.050781,147.05078 81.17187,0 147.05078,-65.87891 147.05078,-147.05078 0,-81.17187 -65.87891,-147.050781 -147.05078,-147.050781 z m 0,264.691401 c -64.84766,0 -117.640625,-52.79296 -117.640625,-117.64062 0,-64.84766 52.792965,-117.640625 117.640625,-117.640625 64.84766,0 117.64062,52.792965 117.64062,117.640625 0,64.84766 -52.79296,117.64062 -117.64062,117.64062 z m 0,0" id="path2" /> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
width="375px"
height="375px"
viewBox="0 0 375 375"
version="1.1"
id="svg5"
sodipodi:docname="copyright.svg"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
>
<defs id="defs9" />
<sodipodi:namedview
id="namedview7"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="2.4012481"
inkscape:cx="194.06574"
inkscape:cy="30.192632"
inkscape:window-width="1920"
inkscape:window-height="995"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg5"
/>
<g id="surface1" transform="matrix(1.2644961,0,0,1.2644961,-49.593016,-49.593016)">
<path
style="fill:{color};fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 159.26562,170.73437 c 0.73438,-4.85156 2.35157,-9.11718 4.41016,-12.79296 2.0625,-3.67579 5,-6.76172 8.67969,-9.11719 3.52734,-2.20313 7.9375,-3.23438 13.3789,-3.37891 3.38282,0.14453 6.47266,0.73438 9.26563,1.91016 2.94141,1.32422 5.58594,3.08594 7.64453,5.29297 2.05859,2.20703 3.67969,4.85156 5,7.79297 1.32422,2.9414 1.91406,6.17578 2.05859,9.41406 h 26.32422 c -0.29297,-6.91406 -1.61718,-13.23438 -4.11718,-18.97266 -2.5,-5.73437 -5.88282,-10.73437 -10.29297,-14.85156 -4.41407,-4.11719 -9.70703,-7.35156 -15.88282,-9.70312 -6.17578,-2.35547 -12.9414,-3.38282 -20.4414,-3.38282 -9.5586,0 -17.9375,1.61719 -24.9961,5 -7.05859,3.38281 -12.9414,7.79297 -17.64843,13.52735 -4.70313,5.73437 -8.23438,12.35156 -10.44141,20 -2.20312,7.64453 -3.52734,15.58593 -3.52734,24.11718 v 3.96875 c 0,8.52735 1.17578,16.46875 3.38281,24.11719 2.20312,7.64453 5.73437,14.26172 10.44141,19.85156 4.70312,5.58594 10.58593,10.14453 17.64453,13.38282 7.05859,3.23437 15.4414,5 25,5 6.91015,0 13.3789,-1.17969 19.41015,-3.38282 6.02735,-2.20703 11.32422,-5.29687 15.87891,-9.26562 4.55859,-3.96875 8.23828,-8.52735 10.88281,-13.82422 2.64844,-5.29297 4.26563,-10.87891 4.41406,-16.91016 h -26.32421 c -0.14454,3.08985 -0.88282,5.88282 -2.20704,8.53125 -1.32031,2.64453 -3.08593,4.85157 -5.29296,6.76172 -2.20313,1.91406 -4.70313,3.38281 -7.64454,4.41406 -2.79687,1.02735 -5.73437,1.32032 -8.82421,1.46875 -5.29297,-0.14843 -9.70704,-1.17578 -13.08594,-3.38281 -3.67969,-2.35156 -6.61719,-5.4414 -8.67969,-9.11719 -2.05859,-3.67578 -3.67578,-8.08593 -4.41016,-12.9375 -0.73437,-4.85546 -1.17578,-9.85546 -1.17578,-14.70703 v -3.96875 c 0,-5.14843 0.44141,-10 1.17578,-14.85547 z M 187.5,40.449219 c -81.17187,0 -147.050781,65.878911 -147.050781,147.050781 0,81.17187 65.878911,147.05078 147.050781,147.05078 81.17187,0 147.05078,-65.87891 147.05078,-147.05078 0,-81.17187 -65.87891,-147.050781 -147.05078,-147.050781 z m 0,264.691401 c -64.84766,0 -117.640625,-52.79296 -117.640625,-117.64062 0,-64.84766 52.792965,-117.640625 117.640625,-117.640625 64.84766,0 117.64062,52.792965 117.64062,117.640625 0,64.84766 -52.79296,117.64062 -117.64062,117.64062 z m 0,0"
id="path2"
/>
</g>
</svg>

View file

@ -1,4 +1,42 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" width="9" height="9" viewBox="0 0 9 9" version="1.1" sodipodi:docname="cross.svg" inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" xmlns="http://www.w3.org/2000/svg" > <path style="fill: none !important;stroke:{color};stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403" d="M 1,4.5 H 8" id="path941"/> <path style="fill: none !important;stroke:{color};stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403" d="M 4.5,1 V 4" id="path941"/> <path style="fill: none !important;stroke:{color};stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403" d="M 4.5,5 V 8" id="path941"/> <path style="fill: none !important;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403" d="M 3.5,5 v 3.5 h 2 v -3 h 3 v -2 h -3 v -3 h -2 v 3 h -3 v 2 h3" id="path941"/> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
width="9"
height="9"
viewBox="0 0 9 9"
version="1.1"
sodipodi:docname="cross.svg"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
xmlns="http://www.w3.org/2000/svg"
>
<path
style="fill: none !important;stroke:{color};stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403"
d="M 1,4.5 H 8"
id="path941"
/>
<path
style="fill: none !important;stroke:{color};stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403"
d="M 4.5,1 V 4"
id="path941"
/>
<path
style="fill: none !important;stroke:{color};stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403"
d="M 4.5,5 V 8"
id="path941"
/>
<path
style="fill: none !important;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403"
d="M 3.5,5 v 3.5 h 2 v -3 h 3 v -2 h -3 v -3 h -2 v 3 h -3 v 2 h3"
id="path941"
/>
</svg>

View file

@ -1,4 +1,30 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:3.439583;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 18.97295 289.3838 L 7.74695 278.1578 " transform="matrix(11.65716,0,0,11.65716,130.176942,-3023.744742)"/> <path style="fill: none !important;stroke-width:3.439583;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 18.989705 278.103849 L 7.763705 289.329515 " transform="matrix(11.65716,0,0,11.65716,130.176942,-3023.744742)"/> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
width="375px"
height="375px"
viewBox="0 0 375 375"
version="1.1"
>
<g id="surface1">
<path
style="fill: none !important;stroke-width:3.439583;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;"
d="M 18.97295 289.3838 L 7.74695 278.1578 "
transform="matrix(11.65716,0,0,11.65716,130.176942,-3023.744742)"
/>
<path
style="fill: none !important;stroke-width:3.439583;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;"
d="M 18.989705 278.103849 L 7.763705 289.329515 "
transform="matrix(11.65716,0,0,11.65716,130.176942,-3023.744742)"
/>
</g>
</svg>

View file

@ -1,4 +1,25 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown width="375px" height="375px" viewBox="0 0 375 375" version="1.1" id="svg15" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <path id="path2" style="color:{color};fill:{color};fill-opacity:0.988235;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none" d="M 187.5 0.17578125 A 15 15 0 0 0 172.5 15.175781 L 172.5 43.708984 C 104.37541 50.343145 49.843699 104.61884 42.837891 172.63672 L 14.765625 172.63672 A 14.86235 14.86235 0 0 0 -0.09765625 187.5 A 14.86235 14.86235 0 0 0 14.765625 202.36133 L 42.837891 202.36133 C 49.842792 270.37794 104.37427 324.65648 172.5 331.29102 L 172.5 360.10156 A 15 15 0 0 0 187.5 375.10156 A 15 15 0 0 0 202.5 360.10156 L 202.5 331.08594 C 269.70108 323.65092 323.26953 269.82518 330.26953 202.5 L 360.08203 202.5 A 15 15 0 0 0 375.08203 187.5 A 15 15 0 0 0 360.08203 172.5 L 330.26953 172.5 C 323.26946 105.17266 269.70061 51.348735 202.5 43.914062 L 202.5 15.175781 A 15 15 0 0 0 187.5 0.17578125 z M 186.5625 80.511719 C 245.87515 80.511719 293.55078 128.18741 293.55078 187.5 C 293.55078 246.80822 245.87443 294.48828 186.5625 294.48828 C 127.25056 294.48828 79.574219 246.80822 79.574219 187.5 C 79.574219 128.1874 127.24984 80.511719 186.5625 80.511719 z M 187.5 139.21094 C 160.83203 139.21094 139.21094 160.83203 139.21094 187.5 C 139.21094 214.16797 160.83203 235.78906 187.5 235.78906 C 214.16797 235.78906 235.78906 214.16797 235.78906 187.5 C 235.78906 160.83203 214.16797 139.21094 187.5 139.21094 z " /> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
width="375px"
height="375px"
viewBox="0 0 375 375"
version="1.1"
id="svg15"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
>
<path
id="path2"
style="color:{color};fill:{color};fill-opacity:0.988235;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
d="M 187.5 0.17578125 A 15 15 0 0 0 172.5 15.175781 L 172.5 43.708984 C 104.37541 50.343145 49.843699 104.61884 42.837891 172.63672 L 14.765625 172.63672 A 14.86235 14.86235 0 0 0 -0.09765625 187.5 A 14.86235 14.86235 0 0 0 14.765625 202.36133 L 42.837891 202.36133 C 49.842792 270.37794 104.37427 324.65648 172.5 331.29102 L 172.5 360.10156 A 15 15 0 0 0 187.5 375.10156 A 15 15 0 0 0 202.5 360.10156 L 202.5 331.08594 C 269.70108 323.65092 323.26953 269.82518 330.26953 202.5 L 360.08203 202.5 A 15 15 0 0 0 375.08203 187.5 A 15 15 0 0 0 360.08203 172.5 L 330.26953 172.5 C 323.26946 105.17266 269.70061 51.348735 202.5 43.914062 L 202.5 15.175781 A 15 15 0 0 0 187.5 0.17578125 z M 186.5625 80.511719 C 245.87515 80.511719 293.55078 128.18741 293.55078 187.5 C 293.55078 246.80822 245.87443 294.48828 186.5625 294.48828 C 127.25056 294.48828 79.574219 246.80822 79.574219 187.5 C 79.574219 128.1874 127.24984 80.511719 186.5625 80.511719 z M 187.5 139.21094 C 160.83203 139.21094 139.21094 160.83203 139.21094 187.5 C 139.21094 214.16797 160.83203 235.78906 187.5 235.78906 C 214.16797 235.78906 235.78906 214.16797 235.78906 187.5 C 235.78906 160.83203 214.16797 139.21094 187.5 139.21094 z "
/>
</svg>

View file

@ -1,4 +1,49 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:2.645833;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 22.034555 283.770823 C 22.034555 288.670301 18.062773 292.642358 13.16302 292.642358 C 8.263267 292.642358 4.291486 288.670301 4.291486 283.770823 C 4.291486 278.871071 8.263267 274.899289 13.16302 274.899289 C 18.062773 274.899289 22.034555 278.871071 22.034555 283.770823 Z M 22.034555 283.770823 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:2.097239;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 3.28414 283.770823 L 1.041796 283.770823 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:2.116667;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 25.405787 283.770823 L 23.286365 283.770823 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:2.116667;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 13.229166 295.948823 L 13.229166 293.831329 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:2.116667;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 13.229166 275.057488 L 13.229166 271.612392 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(33.333334%,33.333334%,92.54902%);fill-opacity:0.988235;" d="M 238.824219 161.203125 L 229.523438 161.203125 L 229.523438 134.96875 C 229.523438 134.96875 229.523438 91.246094 186.066406 91.246094 C 142.609375 91.246094 142.609375 134.96875 142.609375 134.96875 L 142.609375 161.203125 L 133.308594 161.203125 C 124.042969 161.203125 116.535156 168.757812 116.535156 178.082031 L 116.535156 249.347656 C 116.582031 258.636719 124.078125 266.136719 133.308594 266.136719 L 238.824219 266.136719 C 248.085938 266.136719 255.597656 258.582031 255.597656 249.261719 L 255.597656 178.082031 C 255.597656 168.757812 248.085938 161.203125 238.824219 161.203125 Z M 186.066406 231.160156 C 176.464844 231.160156 168.683594 223.328125 168.683594 213.671875 C 168.683594 204.011719 176.464844 196.179688 186.066406 196.179688 C 195.664062 196.179688 203.449219 204.011719 203.449219 213.671875 C 203.449219 223.328125 195.664062 231.160156 186.066406 231.160156 Z M 212.140625 161.203125 L 159.992188 161.203125 L 159.992188 139.339844 C 159.992188 126.226562 159.992188 108.734375 186.066406 108.734375 C 212.140625 108.734375 212.140625 126.226562 212.140625 139.339844 Z M 212.140625 161.203125 "/> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
width="375px"
height="375px"
viewBox="0 0 375 375"
version="1.1"
>
<g id="surface1">
<path
style="fill: none !important;stroke-width:2.645833;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;"
d="M 22.034555 283.770823 C 22.034555 288.670301 18.062773 292.642358 13.16302 292.642358 C 8.263267 292.642358 4.291486 288.670301 4.291486 283.770823 C 4.291486 278.871071 8.263267 274.899289 13.16302 274.899289 C 18.062773 274.899289 22.034555 278.871071 22.034555 283.770823 Z M 22.034555 283.770823 "
transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"
/>
<path
style="fill: none !important;stroke-width:2.097239;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;"
d="M 3.28414 283.770823 L 1.041796 283.770823 "
transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"
/>
<path
style="fill: none !important;stroke-width:2.116667;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;"
d="M 25.405787 283.770823 L 23.286365 283.770823 "
transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"
/>
<path
style="fill: none !important;stroke-width:2.116667;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;"
d="M 13.229166 295.948823 L 13.229166 293.831329 "
transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"
/>
<path
style="fill: none !important;stroke-width:2.116667;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;"
d="M 13.229166 275.057488 L 13.229166 271.612392 "
transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"
/>
<path
style=" stroke:none;fill-rule:nonzero;fill:rgb(33.333334%,33.333334%,92.54902%);fill-opacity:0.988235;"
d="M 238.824219 161.203125 L 229.523438 161.203125 L 229.523438 134.96875 C 229.523438 134.96875 229.523438 91.246094 186.066406 91.246094 C 142.609375 91.246094 142.609375 134.96875 142.609375 134.96875 L 142.609375 161.203125 L 133.308594 161.203125 C 124.042969 161.203125 116.535156 168.757812 116.535156 178.082031 L 116.535156 249.347656 C 116.582031 258.636719 124.078125 266.136719 133.308594 266.136719 L 238.824219 266.136719 C 248.085938 266.136719 255.597656 258.582031 255.597656 249.261719 L 255.597656 178.082031 C 255.597656 168.757812 248.085938 161.203125 238.824219 161.203125 Z M 186.066406 231.160156 C 176.464844 231.160156 168.683594 223.328125 168.683594 213.671875 C 168.683594 204.011719 176.464844 196.179688 186.066406 196.179688 C 195.664062 196.179688 203.449219 204.011719 203.449219 213.671875 C 203.449219 223.328125 195.664062 231.160156 186.066406 231.160156 Z M 212.140625 161.203125 L 159.992188 161.203125 L 159.992188 139.339844 C 159.992188 126.226562 159.992188 108.734375 186.066406 108.734375 C 212.140625 108.734375 212.140625 126.226562 212.140625 139.339844 Z M 212.140625 161.203125 "
/>
</g>
</svg>

View file

@ -1,4 +1,24 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,0%,0%);fill-opacity:1;" d="M 148.457031 148.796875 L 148.457031 269.332031 C 148.457031 271.285156 147.828125 272.890625 146.574219 274.144531 C 145.316406 275.402344 143.714844 276.027344 141.761719 276.027344 L 128.367188 276.027344 C 126.414062 276.027344 124.808594 275.402344 123.554688 274.144531 C 122.296875 272.890625 121.671875 271.285156 121.671875 269.332031 L 121.671875 148.796875 C 121.671875 146.84375 122.296875 145.238281 123.554688 143.984375 C 124.808594 142.726562 126.414062 142.101562 128.367188 142.101562 L 141.761719 142.101562 C 143.714844 142.101562 145.316406 142.726562 146.574219 143.984375 C 147.828125 145.238281 148.457031 146.84375 148.457031 148.796875 Z M 202.027344 148.796875 L 202.027344 269.332031 C 202.027344 271.285156 201.398438 272.890625 200.144531 274.144531 C 198.890625 275.402344 197.285156 276.027344 195.332031 276.027344 L 181.9375 276.027344 C 179.984375 276.027344 178.382812 275.402344 177.125 274.144531 C 175.871094 272.890625 175.242188 271.285156 175.242188 269.332031 L 175.242188 148.796875 C 175.242188 146.84375 175.871094 145.238281 177.125 143.984375 C 178.382812 142.726562 179.984375 142.101562 181.9375 142.101562 L 195.332031 142.101562 C 197.285156 142.101562 198.890625 142.726562 200.144531 143.984375 C 201.398438 145.238281 202.027344 146.84375 202.027344 148.796875 Z M 255.597656 148.796875 L 255.597656 269.332031 C 255.597656 271.285156 254.972656 272.890625 253.714844 274.144531 C 252.460938 275.402344 250.855469 276.027344 248.902344 276.027344 L 235.511719 276.027344 C 233.558594 276.027344 231.953125 275.402344 230.695312 274.144531 C 229.441406 272.890625 228.8125 271.285156 228.8125 269.332031 L 228.8125 148.796875 C 228.8125 146.84375 229.441406 145.238281 230.695312 143.984375 C 231.953125 142.726562 233.558594 142.101562 235.511719 142.101562 L 248.902344 142.101562 C 250.855469 142.101562 252.460938 142.726562 253.714844 143.984375 C 254.972656 145.238281 255.597656 146.84375 255.597656 148.796875 Z M 282.386719 300.304688 L 282.386719 101.921875 L 94.886719 101.921875 L 94.886719 300.304688 C 94.886719 303.371094 95.375 306.199219 96.351562 308.777344 C 97.328125 311.359375 98.335938 313.242188 99.382812 314.429688 C 100.429688 315.613281 101.164062 316.207031 101.582031 316.207031 L 275.6875 316.207031 C 276.105469 316.207031 276.839844 315.613281 277.886719 314.429688 C 278.933594 313.242188 279.945312 311.359375 280.921875 308.777344 C 281.898438 306.199219 282.386719 303.371094 282.386719 300.304688 Z M 141.761719 75.136719 L 235.511719 75.136719 L 225.464844 50.652344 C 224.488281 49.398438 223.304688 48.628906 221.90625 48.351562 L 155.570312 48.351562 C 154.175781 48.628906 152.992188 49.398438 152.015625 50.652344 Z M 335.957031 81.832031 L 335.957031 95.226562 C 335.957031 97.179688 335.328125 98.78125 334.074219 100.039062 C 332.816406 101.292969 331.214844 101.921875 329.261719 101.921875 L 309.171875 101.921875 L 309.171875 300.304688 C 309.171875 311.882812 305.890625 321.894531 299.335938 330.332031 C 292.777344 338.773438 284.894531 342.992188 275.6875 342.992188 L 101.582031 342.992188 C 92.375 342.992188 84.492188 338.914062 77.933594 330.75 C 71.378906 322.589844 68.097656 312.71875 68.097656 301.140625 L 68.097656 101.921875 L 48.011719 101.921875 C 46.058594 101.921875 44.453125 101.292969 43.195312 100.039062 C 41.941406 98.78125 41.3125 97.179688 41.3125 95.226562 L 41.3125 81.832031 C 41.3125 79.878906 41.941406 78.273438 43.195312 77.019531 C 44.453125 75.765625 46.058594 75.136719 48.011719 75.136719 L 112.671875 75.136719 L 127.320312 40.1875 C 129.414062 35.027344 133.179688 30.632812 138.621094 27.003906 C 144.0625 23.378906 149.574219 21.566406 155.152344 21.566406 L 222.117188 21.566406 C 227.699219 21.566406 233.207031 23.378906 238.648438 27.003906 C 244.089844 30.632812 247.855469 35.027344 249.949219 40.1875 L 264.597656 75.136719 L 329.261719 75.136719 C 331.214844 75.136719 332.816406 75.765625 334.074219 77.019531 C 335.328125 78.273438 335.957031 79.878906 335.957031 81.832031 Z M 335.957031 81.832031 "/> </g> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns="http://www.w3.org/2000/svg"
width="375px"
height="375px"
viewBox="0 0 375 375"
version="1.1"
>
<g id="surface1">
<path
style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,0%,0%);fill-opacity:1;"
d="M 148.457031 148.796875 L 148.457031 269.332031 C 148.457031 271.285156 147.828125 272.890625 146.574219 274.144531 C 145.316406 275.402344 143.714844 276.027344 141.761719 276.027344 L 128.367188 276.027344 C 126.414062 276.027344 124.808594 275.402344 123.554688 274.144531 C 122.296875 272.890625 121.671875 271.285156 121.671875 269.332031 L 121.671875 148.796875 C 121.671875 146.84375 122.296875 145.238281 123.554688 143.984375 C 124.808594 142.726562 126.414062 142.101562 128.367188 142.101562 L 141.761719 142.101562 C 143.714844 142.101562 145.316406 142.726562 146.574219 143.984375 C 147.828125 145.238281 148.457031 146.84375 148.457031 148.796875 Z M 202.027344 148.796875 L 202.027344 269.332031 C 202.027344 271.285156 201.398438 272.890625 200.144531 274.144531 C 198.890625 275.402344 197.285156 276.027344 195.332031 276.027344 L 181.9375 276.027344 C 179.984375 276.027344 178.382812 275.402344 177.125 274.144531 C 175.871094 272.890625 175.242188 271.285156 175.242188 269.332031 L 175.242188 148.796875 C 175.242188 146.84375 175.871094 145.238281 177.125 143.984375 C 178.382812 142.726562 179.984375 142.101562 181.9375 142.101562 L 195.332031 142.101562 C 197.285156 142.101562 198.890625 142.726562 200.144531 143.984375 C 201.398438 145.238281 202.027344 146.84375 202.027344 148.796875 Z M 255.597656 148.796875 L 255.597656 269.332031 C 255.597656 271.285156 254.972656 272.890625 253.714844 274.144531 C 252.460938 275.402344 250.855469 276.027344 248.902344 276.027344 L 235.511719 276.027344 C 233.558594 276.027344 231.953125 275.402344 230.695312 274.144531 C 229.441406 272.890625 228.8125 271.285156 228.8125 269.332031 L 228.8125 148.796875 C 228.8125 146.84375 229.441406 145.238281 230.695312 143.984375 C 231.953125 142.726562 233.558594 142.101562 235.511719 142.101562 L 248.902344 142.101562 C 250.855469 142.101562 252.460938 142.726562 253.714844 143.984375 C 254.972656 145.238281 255.597656 146.84375 255.597656 148.796875 Z M 282.386719 300.304688 L 282.386719 101.921875 L 94.886719 101.921875 L 94.886719 300.304688 C 94.886719 303.371094 95.375 306.199219 96.351562 308.777344 C 97.328125 311.359375 98.335938 313.242188 99.382812 314.429688 C 100.429688 315.613281 101.164062 316.207031 101.582031 316.207031 L 275.6875 316.207031 C 276.105469 316.207031 276.839844 315.613281 277.886719 314.429688 C 278.933594 313.242188 279.945312 311.359375 280.921875 308.777344 C 281.898438 306.199219 282.386719 303.371094 282.386719 300.304688 Z M 141.761719 75.136719 L 235.511719 75.136719 L 225.464844 50.652344 C 224.488281 49.398438 223.304688 48.628906 221.90625 48.351562 L 155.570312 48.351562 C 154.175781 48.628906 152.992188 49.398438 152.015625 50.652344 Z M 335.957031 81.832031 L 335.957031 95.226562 C 335.957031 97.179688 335.328125 98.78125 334.074219 100.039062 C 332.816406 101.292969 331.214844 101.921875 329.261719 101.921875 L 309.171875 101.921875 L 309.171875 300.304688 C 309.171875 311.882812 305.890625 321.894531 299.335938 330.332031 C 292.777344 338.773438 284.894531 342.992188 275.6875 342.992188 L 101.582031 342.992188 C 92.375 342.992188 84.492188 338.914062 77.933594 330.75 C 71.378906 322.589844 68.097656 312.71875 68.097656 301.140625 L 68.097656 101.921875 L 48.011719 101.921875 C 46.058594 101.921875 44.453125 101.292969 43.195312 100.039062 C 41.941406 98.78125 41.3125 97.179688 41.3125 95.226562 L 41.3125 81.832031 C 41.3125 79.878906 41.941406 78.273438 43.195312 77.019531 C 44.453125 75.765625 46.058594 75.136719 48.011719 75.136719 L 112.671875 75.136719 L 127.320312 40.1875 C 129.414062 35.027344 133.179688 30.632812 138.621094 27.003906 C 144.0625 23.378906 149.574219 21.566406 155.152344 21.566406 L 222.117188 21.566406 C 227.699219 21.566406 233.207031 23.378906 238.648438 27.003906 C 244.089844 30.632812 247.855469 35.027344 249.949219 40.1875 L 264.597656 75.136719 L 329.261719 75.136719 C 331.214844 75.136719 332.816406 75.765625 334.074219 77.019531 C 335.328125 78.273438 335.957031 79.878906 335.957031 81.832031 Z M 335.957031 81.832031 "
/>
</g>
</svg>

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,104 @@
<script>
export let color = "#000000"
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns="http://www.w3.org/2000/svg" version="1.0" width="860.50732pt" height="860.50732pt" viewBox="0 0 860.50732 860.50732" preserveAspectRatio="xMidYMid meet" id="svg14" sodipodi:docname="direction_gradient.svg" inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"> <defs id="defs18"> <linearGradient inkscape:collect="always" id="linearGradient832"> <stop style="stop-color:{color};stop-opacity:1;" offset="0" id="stop828"/> <stop style="stop-color:{color};stop-opacity:0;" offset="1" id="stop830"/> </linearGradient> <radialGradient inkscape:collect="always" xlink:href="#linearGradient832" id="radialGradient838" cx="430.25363" cy="519.61188" fx="430.25363" fy="519.61188" r="305.54589" gradientTransform="matrix(0.95288409,-0.94890664,0.94542304,0.94938587,-470.98122,345.21193)" gradientUnits="userSpaceOnUse"/> </defs> <sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1920" inkscape:window-height="999" id="namedview16" showgrid="false" showguides="true" inkscape:guide-bbox="true" inkscape:zoom="0.70710678" inkscape:cx="279.00239" inkscape:cy="856.75313" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg14"> <sodipodi:guide position="430.25363,862.49682" orientation="1,0" id="guide832" inkscape:locked="false"/> <sodipodi:guide position="-42.427977,430.25368" orientation="0,1" id="guide834" inkscape:locked="false"/> <sodipodi:guide position="398.27788,720.18823" orientation="0,1" id="guide840" inkscape:locked="false"/> </sodipodi:namedview> <metadata id="metadata2"> Created by potrace 1.15, written by Peter Selinger 2001-2017 <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> <dc:title/> </cc:Work> </rdf:RDF> </metadata> <path style="fill:url(#radialGradient838);fill-opacity:1;stroke:none;stroke-width:2.83464575;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M 735.79979,124.70799 C 654.79116,43.598883 544.88842,-2.0206645 430.25389,-2.121103 315.61937,-2.0206592 205.71663,43.598888 124.70801,124.70799 l 305.54588,305.54589 z" id="path836" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/> </svg>
<svg
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
on:keydown
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns="http://www.w3.org/2000/svg"
version="1.0"
width="860.50732pt"
height="860.50732pt"
viewBox="0 0 860.50732 860.50732"
preserveAspectRatio="xMidYMid meet"
id="svg14"
sodipodi:docname="direction_gradient.svg"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
>
<defs id="defs18">
<linearGradient inkscape:collect="always" id="linearGradient832">
<stop style="stop-color:{color};stop-opacity:1;" offset="0" id="stop828" />
<stop style="stop-color:{color};stop-opacity:0;" offset="1" id="stop830" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient832"
id="radialGradient838"
cx="430.25363"
cy="519.61188"
fx="430.25363"
fy="519.61188"
r="305.54589"
gradientTransform="matrix(0.95288409,-0.94890664,0.94542304,0.94938587,-470.98122,345.21193)"
gradientUnits="userSpaceOnUse"
/>
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="999"
id="namedview16"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:zoom="0.70710678"
inkscape:cx="279.00239"
inkscape:cy="856.75313"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg14"
>
<sodipodi:guide
position="430.25363,862.49682"
orientation="1,0"
id="guide832"
inkscape:locked="false"
/>
<sodipodi:guide
position="-42.427977,430.25368"
orientation="0,1"
id="guide834"
inkscape:locked="false"
/>
<sodipodi:guide
position="398.27788,720.18823"
orientation="0,1"
id="guide840"
inkscape:locked="false"
/>
</sodipodi:namedview>
<metadata id="metadata2">
Created by potrace 1.15, written by Peter Selinger 2001-2017 <rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<path
style="fill:url(#radialGradient838);fill-opacity:1;stroke:none;stroke-width:2.83464575;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 735.79979,124.70799 C 654.79116,43.598883 544.88842,-2.0206645 430.25389,-2.121103 315.61937,-2.0206592 205.71663,43.598888 124.70801,124.70799 l 305.54588,305.54589 z"
id="path836"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
/>
</svg>

Some files were not shown because too many files have changed in this diff Show more