forked from MapComplete/MapComplete
		
	Move various tabs into buttons, more work on a11y
This commit is contained in:
		
							parent
							
								
									cce9b879f2
								
							
						
					
					
						commit
						7e852dd7e3
					
				
					 29 changed files with 10642 additions and 10432 deletions
				
			
		
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -2227,7 +2227,7 @@ | |||
|           } | ||||
|         } | ||||
|       ] | ||||
|     },   | ||||
|     }, | ||||
|     { | ||||
|       "id": "internet-ssid", | ||||
|       "labels": [ | ||||
|  |  | |||
|  | @ -463,6 +463,7 @@ | |||
|         "key": "Key combination", | ||||
|         "openFilterPanel": "Opens the POI-layers and filter panel", | ||||
|         "openLayersPanel": "Opens the background layers panel", | ||||
|         "queryCurrentLocation": "Display the address which is nearest the map center", | ||||
|         "selectAerial": "Set the background to aerial or satellite imagery. Toggles between the two best, available layers", | ||||
|         "selectFavourites": "Open the favourites page", | ||||
|         "selectItem": "Select the POI which is closest to the map center (crosshair). Only when in keyboard navigation is used", | ||||
|  |  | |||
							
								
								
									
										20244
									
								
								langs/layers/de.json
									
										
									
									
									
								
							
							
						
						
									
										20244
									
								
								langs/layers/de.json
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -7154,6 +7154,7 @@ | |||
|                 "question": "Are dogs allowed in this business?" | ||||
|             }, | ||||
|             "email": { | ||||
|                 "editButtonAriaLabel": "Edit email address", | ||||
|                 "question": "What is the email address of {title()}?" | ||||
|             }, | ||||
|             "gluten_free": { | ||||
|  | @ -7352,6 +7353,7 @@ | |||
|                 } | ||||
|             }, | ||||
|             "phone": { | ||||
|                 "editButtonAriaLabel": "Edit phone number", | ||||
|                 "question": "What is the phone number of {title()}?" | ||||
|             }, | ||||
|             "repeated": { | ||||
|  | @ -7454,6 +7456,7 @@ | |||
|                 "question": "Does this place offer a vegan option?" | ||||
|             }, | ||||
|             "website": { | ||||
|                 "editButtonAriaLabel": "Edit website", | ||||
|                 "question": "What is the website of {title()}?" | ||||
|             }, | ||||
|             "wheelchair-access": { | ||||
|  |  | |||
|  | @ -6338,6 +6338,7 @@ | |||
|                 "question": "Zijn honden toegelaten in deze zaak?" | ||||
|             }, | ||||
|             "email": { | ||||
|                 "editButtonAriaLabel": "Pas emailadres aan", | ||||
|                 "question": "Wat is het e-mailadres van {title()}?" | ||||
|             }, | ||||
|             "induction-loop": { | ||||
|  | @ -6482,6 +6483,7 @@ | |||
|                 } | ||||
|             }, | ||||
|             "phone": { | ||||
|                 "editButtonAriaLabel": "Pas telefoonnummer aan", | ||||
|                 "question": "Wat is het telefoonnummer van {title()}?" | ||||
|             }, | ||||
|             "repeated": { | ||||
|  | @ -6540,6 +6542,7 @@ | |||
|                 "question": "Is roken toegestaan bij {title()}?" | ||||
|             }, | ||||
|             "website": { | ||||
|                 "editButtonAriaLabel": "Pas website aan", | ||||
|                 "question": "Wat is de website van {title()}?" | ||||
|             }, | ||||
|             "wheelchair-access": { | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| { | ||||
|   "name": "mapcomplete", | ||||
|   "version": "0.36.6", | ||||
|   "version": "0.36.7", | ||||
|   "repository": "https://github.com/pietervdvn/MapComplete", | ||||
|   "description": "A small website to edit OSM easily", | ||||
|   "bugs": "https://github.com/pietervdvn/MapComplete/issues", | ||||
|  | @ -32,7 +32,7 @@ | |||
|       "https://overpass.openstreetmap.ru/cgi/interpreter" | ||||
|     ], | ||||
|     "country_coder_host": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/latlon2country", | ||||
|     "nominatimEndpoint": "https://nominatim.openstreetmap.org/" | ||||
|     "nominatimEndpoint": "https://geocoding.geofabrik.de/b75350b1cfc34962ac49824fe5b582dc/" | ||||
|   }, | ||||
|   "scripts": { | ||||
|     "start": "npm run generate:layeroverview && npm run strt", | ||||
|  | @ -75,7 +75,7 @@ | |||
|     "lint:prettier": "prettier  --check '**/*.ts' '**/*.svelte'", | ||||
|     "format": "prettier --write '**/*.ts' '**/*.svelte'", | ||||
|     "clean:tests": "find . -type f -name \"*.doctest.ts\" | xargs -r rm", | ||||
|     "clean": "rm -rf .cache/ && (find *.html | grep -v \"^\\(404\\|index\\|land\\|test\\|studio\\|theme\\|style_test\\|statistics\\|leaderboard\\).html\" | xargs -r rm) && (ls | grep \"^index_[a-zA-Z_-]\\+\\.ts$\" | xargs -r rm)", | ||||
|     "clean": "rm -rf .cache/ && (find *.html | grep -v \"^\\(404\\|index\\|land\\|privacy\\|test\\|studio\\|theme\\|style_test\\|statistics\\|leaderboard\\).html\" | xargs -r rm) && (ls | grep \"^index_[a-zA-Z_-]\\+\\.ts$\" | xargs -r rm)", | ||||
|     "generate:dependency-graph": "node_modules/.bin/depcruise --exclude \"^node_modules\" --output-type dot Logic/State/MapState.ts > dependencies.dot && dot dependencies.dot -T svg -o dependencies.svg && rm dependencies.dot", | ||||
|     "weblate-add-upstream": "git remote add weblate-github git@github.com:weblate/MapComplete.git && git remote add weblate-hosted-core https://hosted.weblate.org/git/mapcomplete/core/ && git remote add weblate-hosted-layers https://hosted.weblate.org/git/mapcomplete/layers/", | ||||
|     "weblate-merge": "git remote update weblate-github; git merge weblate-github/weblate-mapcomplete-core weblate-github/weblate-mapcomplete-layers weblate-github/weblate-mapcomplete-layer-translations", | ||||
|  |  | |||
|  | @ -1071,14 +1071,14 @@ video { | |||
|   height: 6rem; | ||||
| } | ||||
| 
 | ||||
| .h-screen { | ||||
|   height: 100vh; | ||||
| } | ||||
| 
 | ||||
| .h-full { | ||||
|   height: 100%; | ||||
| } | ||||
| 
 | ||||
| .h-screen { | ||||
|   height: 100vh; | ||||
| } | ||||
| 
 | ||||
| .h-32 { | ||||
|   height: 8rem; | ||||
| } | ||||
|  | @ -1684,6 +1684,11 @@ video { | |||
|   border-color: rgb(0 0 0 / var(--tw-border-opacity)); | ||||
| } | ||||
| 
 | ||||
| .border-gray-500 { | ||||
|   --tw-border-opacity: 1; | ||||
|   border-color: rgb(107 114 128 / var(--tw-border-opacity)); | ||||
| } | ||||
| 
 | ||||
| .border-subtle { | ||||
|   --tw-border-opacity: 1; | ||||
|   border-color: rgb(219 234 254 / var(--tw-border-opacity)); | ||||
|  | @ -1709,11 +1714,6 @@ video { | |||
|   border-color: rgb(156 163 175 / var(--tw-border-opacity)); | ||||
| } | ||||
| 
 | ||||
| .border-gray-500 { | ||||
|   --tw-border-opacity: 1; | ||||
|   border-color: rgb(107 114 128 / var(--tw-border-opacity)); | ||||
| } | ||||
| 
 | ||||
| .border-gray-800 { | ||||
|   --tw-border-opacity: 1; | ||||
|   border-color: rgb(31 41 55 / var(--tw-border-opacity)); | ||||
|  | @ -1770,14 +1770,14 @@ video { | |||
|   padding: 2rem; | ||||
| } | ||||
| 
 | ||||
| .p-2 { | ||||
|   padding: 0.5rem; | ||||
| } | ||||
| 
 | ||||
| .p-4 { | ||||
|   padding: 1rem; | ||||
| } | ||||
| 
 | ||||
| .p-2 { | ||||
|   padding: 0.5rem; | ||||
| } | ||||
| 
 | ||||
| .p-1 { | ||||
|   padding: 0.25rem; | ||||
| } | ||||
|  | @ -1814,6 +1814,10 @@ video { | |||
|   padding-right: 0.75rem; | ||||
| } | ||||
| 
 | ||||
| .pr-2 { | ||||
|   padding-right: 0.5rem; | ||||
| } | ||||
| 
 | ||||
| .pr-12 { | ||||
|   padding-right: 3rem; | ||||
| } | ||||
|  | @ -1822,8 +1826,8 @@ video { | |||
|   padding-left: 0.25rem; | ||||
| } | ||||
| 
 | ||||
| .pr-2 { | ||||
|   padding-right: 0.5rem; | ||||
| .pr-1 { | ||||
|   padding-right: 0.25rem; | ||||
| } | ||||
| 
 | ||||
| .pl-2 { | ||||
|  | @ -1854,10 +1858,6 @@ video { | |||
|   padding-left: 1rem; | ||||
| } | ||||
| 
 | ||||
| .pr-1 { | ||||
|   padding-right: 0.25rem; | ||||
| } | ||||
| 
 | ||||
| .pl-3 { | ||||
|   padding-left: 0.75rem; | ||||
| } | ||||
|  | @ -2509,6 +2509,11 @@ label.checked:not(.neutral-label) { | |||
|   width: 100%; | ||||
| } | ||||
| 
 | ||||
| button.soft, .button.soft { | ||||
|   border: 2px solid var(--interactive-background); | ||||
|   margin: 0; | ||||
| } | ||||
| 
 | ||||
| .links-as-button a { | ||||
|   /* | ||||
|     * Let a 'link' mimick a button, but not entirely | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ export class BBox { | |||
|      * Coordinates should be [[lon, lat],[lon, lat]] | ||||
|      * @param coordinates | ||||
|      */ | ||||
|     constructor(coordinates) { | ||||
|     constructor(coordinates: [number,number][]) { | ||||
|         this.maxLat = -90 | ||||
|         this.maxLon = -180 | ||||
|         this.minLat = 90 | ||||
|  |  | |||
|  | @ -29,13 +29,14 @@ export class Geocoding { | |||
| 
 | ||||
|     static async reverse( | ||||
|         coordinate: { lon: number; lat: number }, | ||||
|         zoom: number = 18 | ||||
|         zoom: number = 17, | ||||
|         language?: string | ||||
|     ): Promise<FeatureCollection> { | ||||
|         // https://nominatim.org/release-docs/develop/api/Reverse/
 | ||||
|         // IF the zoom is low, it'll only return a country instead of an address
 | ||||
|         const url = `${Geocoding.host}reverse?format=geojson&lat=${coordinate.lat}&lon=${ | ||||
|             coordinate.lon | ||||
|         }&zoom=${Math.round(zoom)}` | ||||
|         }&zoom=${Math.ceil(zoom) + 1}&accept-language=${language}` | ||||
|         return Utils.downloadJson(url) | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,42 +1,14 @@ | |||
| import { Utils } from "../../Utils" | ||||
| /** This code is autogenerated - do not edit. Edit ./assets/layers/usersettings/usersettings.json instead */ | ||||
| export class ThemeMetaTagging { | ||||
|     public static readonly themeName = "usersettings" | ||||
|    public static readonly themeName = "usersettings" | ||||
| 
 | ||||
|     public metaTaggging_for_usersettings(feat: { properties: Record<string, string> }) { | ||||
|         Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_md", () => | ||||
|             feat.properties._description | ||||
|                 .match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/) | ||||
|                 ?.at(1) | ||||
|         ) | ||||
|         Utils.AddLazyProperty( | ||||
|             feat.properties, | ||||
|             "_d", | ||||
|             () => feat.properties._description?.replace(/</g, "<")?.replace(/>/g, ">") ?? "" | ||||
|         ) | ||||
|         Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_a", () => | ||||
|             ((feat) => { | ||||
|                 const e = document.createElement("div") | ||||
|                 e.innerHTML = feat.properties._d | ||||
|                 return Array.from(e.getElementsByTagName("a")).filter( | ||||
|                     (a) => a.href.match(/mastodon|en.osm.town/) !== null | ||||
|                 )[0]?.href | ||||
|             })(feat) | ||||
|         ) | ||||
|         Utils.AddLazyProperty(feat.properties, "_mastodon_link", () => | ||||
|             ((feat) => { | ||||
|                 const e = document.createElement("div") | ||||
|                 e.innerHTML = feat.properties._d | ||||
|                 return Array.from(e.getElementsByTagName("a")).filter( | ||||
|                     (a) => a.getAttribute("rel")?.indexOf("me") >= 0 | ||||
|                 )[0]?.href | ||||
|             })(feat) | ||||
|         ) | ||||
|         Utils.AddLazyProperty( | ||||
|             feat.properties, | ||||
|             "_mastodon_candidate", | ||||
|             () => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a | ||||
|         ) | ||||
|         feat.properties["__current_backgroun"] = "initial_value" | ||||
|     } | ||||
| } | ||||
|    public metaTaggging_for_usersettings(feat: {properties: Record<string, string>}) { | ||||
|       Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_md', () => feat.properties._description.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)?.at(1) )  | ||||
|       Utils.AddLazyProperty(feat.properties, '_d', () => feat.properties._description?.replace(/</g,'<')?.replace(/>/g,'>') ?? '' )  | ||||
|       Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_a', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.href.match(/mastodon|en.osm.town/) !== null)[0]?.href   }) (feat)  )  | ||||
|       Utils.AddLazyProperty(feat.properties, '_mastodon_link', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.getAttribute("rel")?.indexOf('me') >= 0)[0]?.href})(feat)  )  | ||||
|       Utils.AddLazyProperty(feat.properties, '_mastodon_candidate', () => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a )  | ||||
|       feat.properties['__current_backgroun'] = 'initial_value' | ||||
|    } | ||||
| } | ||||
|  | @ -34,7 +34,8 @@ export class MenuState { | |||
|         new UIEventSource<boolean>(false) | ||||
| 
 | ||||
|     public readonly filtersPanelIsOpened: UIEventSource<boolean> = new UIEventSource<boolean>(false) | ||||
| 
 | ||||
|     public readonly privacyPanelIsOpened: UIEventSource<boolean> = new UIEventSource<boolean>(false) | ||||
|     public readonly communityIndexPanelIsOpened: UIEventSource<boolean> = new UIEventSource(false) | ||||
|     public readonly allToggles: { | ||||
|         toggle: UIEventSource<boolean> | ||||
|         name: string | ||||
|  | @ -151,13 +152,21 @@ export class MenuState { | |||
|      */ | ||||
|     public closeAll(): boolean { | ||||
|         const toggles = [ | ||||
|             this.menuIsOpened, | ||||
|             this.themeIsOpened, | ||||
|             this.communityIndexPanelIsOpened, | ||||
|             this.privacyPanelIsOpened, | ||||
|             this.backgroundLayerSelectionIsOpened, | ||||
|             this.filtersPanelIsOpened, | ||||
|             this.menuIsOpened, | ||||
|             this.themeIsOpened, | ||||
|         ] | ||||
|         const somethingIsOpen = toggles.some((t) => t.data) | ||||
|         toggles.forEach((t) => t.setData(false)) | ||||
|         let somethingIsOpen = false | ||||
|         for (const t of toggles) { | ||||
|             somethingIsOpen = t.data | ||||
|             t.setData(false) | ||||
|             if (somethingIsOpen) { | ||||
|                 break | ||||
|             } | ||||
|         } | ||||
|         return somethingIsOpen | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -487,35 +487,28 @@ export default class ThemeViewState implements SpecialVisualizationState { | |||
|     } | ||||
| 
 | ||||
|     private initHotkeys() { | ||||
|         Hotkeys.RegisterHotkey( | ||||
|             { nomod: "Escape", onUp: true }, | ||||
|             Translations.t.hotkeyDocumentation.closeSidebar, | ||||
|             () => { | ||||
|                 if (this.previewedImage.data !== undefined) { | ||||
|                     this.previewedImage.setData(undefined) | ||||
|                     return | ||||
|                 } | ||||
|                 this.selectedElement.setData(undefined) | ||||
|                 this.guistate.closeAll() | ||||
|                 this.focusOnMap() | ||||
|         const docs = Translations.t.hotkeyDocumentation | ||||
|         Hotkeys.RegisterHotkey({ nomod: "Escape", onUp: true }, docs.closeSidebar, () => { | ||||
|             if (this.previewedImage.data !== undefined) { | ||||
|                 this.previewedImage.setData(undefined) | ||||
|                 return | ||||
|             } | ||||
|         ) | ||||
|             this.selectedElement.setData(undefined) | ||||
|             this.guistate.closeAll() | ||||
|             this.focusOnMap() | ||||
|         }) | ||||
| 
 | ||||
|         Hotkeys.RegisterHotkey( | ||||
|             { nomod: "f" }, | ||||
|             Translations.t.hotkeyDocumentation.selectFavourites, | ||||
|             () => { | ||||
|                 this.guistate.menuViewTab.setData("favourites") | ||||
|                 this.guistate.menuIsOpened.setData(true) | ||||
|             } | ||||
|         ) | ||||
|         Hotkeys.RegisterHotkey({ nomod: "f" }, docs.selectFavourites, () => { | ||||
|             this.guistate.menuViewTab.setData("favourites") | ||||
|             this.guistate.menuIsOpened.setData(true) | ||||
|         }) | ||||
| 
 | ||||
|         Hotkeys.RegisterHotkey( | ||||
|             { | ||||
|                 nomod: " ", | ||||
|                 onUp: true, | ||||
|             }, | ||||
|             Translations.t.hotkeyDocumentation.selectItem, | ||||
|             docs.selectItem, | ||||
|             () => { | ||||
|                 if (this.selectedElement.data !== undefined) { | ||||
|                     return false | ||||
|  | @ -537,7 +530,7 @@ export default class ThemeViewState implements SpecialVisualizationState { | |||
|                     nomod: "" + i, | ||||
|                     onUp: true, | ||||
|                 }, | ||||
|                 Translations.t.hotkeyDocumentation.selectItem, | ||||
|                 docs.selectItem, | ||||
|                 () => this.selectClosestAtCenter(i - 1) | ||||
|             ) | ||||
|         } | ||||
|  | @ -550,7 +543,7 @@ export default class ThemeViewState implements SpecialVisualizationState { | |||
|                 { | ||||
|                     nomod: "b", | ||||
|                 }, | ||||
|                 Translations.t.hotkeyDocumentation.openLayersPanel, | ||||
|                 docs.openLayersPanel, | ||||
|                 () => { | ||||
|                     if (this.featureSwitches.featureSwitchBackgroundSelection.data) { | ||||
|                         this.guistate.backgroundLayerSelectionIsOpened.setData(true) | ||||
|  | @ -563,6 +556,7 @@ export default class ThemeViewState implements SpecialVisualizationState { | |||
|                 }, | ||||
|                 Translations.t.hotkeyDocumentation.openFilterPanel, | ||||
|                 () => { | ||||
|                     console.log("S pressed") | ||||
|                     if (this.featureSwitches.featureSwitchFilter.data) { | ||||
|                         this.guistate.openFilterView() | ||||
|                     } | ||||
|  | @ -646,7 +640,7 @@ export default class ThemeViewState implements SpecialVisualizationState { | |||
| 
 | ||||
|         this.closestFeatures.registerSource(specialLayers.favourite, "favourite") | ||||
|         if (this.layout?.lockLocation) { | ||||
|             const bbox = new BBox(this.layout.lockLocation) | ||||
|             const bbox = new BBox(<any>this.layout.lockLocation) | ||||
|             this.mapProperties.maxbounds.setData(bbox) | ||||
|             ShowDataLayer.showRange( | ||||
|                 this.map, | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ | |||
|   import { LayoutInformation } from "../Models/ThemeConfig/LayoutConfig" | ||||
|   import * as themeOverview from "../assets/generated/theme_overview.json" | ||||
|   import UnofficialThemeList from "./BigComponents/UnofficialThemeList.svelte" | ||||
|   import Eye from "@babeard/svelte-heroicons/mini/Eye" | ||||
| 
 | ||||
|   const featureSwitches = new OsmConnectionFeatureSwitches() | ||||
|   const osmConnection = new OsmConnection({ | ||||
|  | @ -136,6 +137,14 @@ | |||
|       <Tr t={Translations.t.general.morescreen.createYourOwnTheme} /> | ||||
|     </a> | ||||
| 
 | ||||
|     <a | ||||
|       class="button h-fit w-full" | ||||
|       href={window.location.protocol + "//" + window.location.host + "/privacy.html"} | ||||
|     > | ||||
|       <Eye class="mr-2 h-6 w-6" /> | ||||
|       <Tr t={Translations.t.privacy.title} /> | ||||
|     </a> | ||||
| 
 | ||||
| 
 | ||||
|   </LoginToggle> | ||||
| 
 | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ | |||
|     <slot name="close-button"> | ||||
|       <!-- The close button is placed _after_ the default slot in order to always paint it on top --> | ||||
|       <button | ||||
|         class="absolute right-10 top-10 h-8 w-8 cursor-pointer border-none bg-white p-0" | ||||
|         class="absolute right-10 top-10 h-8 w-8 cursor-pointer border-none bg-white rounded-full p-0" | ||||
|         on:click={() => dispatch("close")} | ||||
|       > | ||||
|         <XCircleIcon /> | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ | |||
| > | ||||
|   <slot name="close-button"> | ||||
|     <button | ||||
|       class="absolute right-10 top-10 h-8 w-8 cursor-pointer" | ||||
|       class="absolute right-10 top-10 h-8 w-8 cursor-pointer rounded-full" | ||||
|       on:click={() => dispatch("close")} | ||||
|     > | ||||
|       <XCircleIcon /> | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
|   import Josm_logo from "../../assets/svg/Josm_logo.svelte" | ||||
|   import Constants from "../../Models/Constants" | ||||
|   import type { SpecialVisualizationState } from "../SpecialVisualization" | ||||
|   import { Utils } from "../../Utils" | ||||
| 
 | ||||
|   export let state: SpecialVisualizationState | ||||
|   const t = Translations.t.general.attribution | ||||
|  | @ -13,7 +14,7 @@ | |||
|   josmState.stabilized(15000).addCallbackD(() => josmState.setData(undefined)) | ||||
| 
 | ||||
|   const showButton = state.osmConnection.userDetails.map( | ||||
|     (ud) => ud.loggedIn && ud.csCount >= Constants.userJourney.historyLinkVisible | ||||
|     (ud) => ud.loggedIn && ud.csCount >= Constants.userJourney.historyLinkVisible, | ||||
|   ) | ||||
| 
 | ||||
|   function openJosm() { | ||||
|  | @ -33,16 +34,20 @@ | |||
| </script> | ||||
| 
 | ||||
| {#if $showButton} | ||||
|   {#if $josmState === undefined} | ||||
|     <!-- empty --> | ||||
|   {:else if state === "OK"} | ||||
|     <Tr cls="thanks" t={t.josmOpened} /> | ||||
|   {:else} | ||||
|     <Tr cls="alert" t={t.josmNotOpened} /> | ||||
|   {/if} | ||||
|   <div class="flex"> | ||||
| 
 | ||||
|     <button class="flex items-center small soft grow" on:click={openJosm}> | ||||
|       <Josm_logo class="h-6 w-6 pr-2" /> | ||||
|       <Tr t={t.editJosm} /> | ||||
|     </button> | ||||
| 
 | ||||
|     {#if $josmState === undefined} | ||||
|       <!-- empty --> | ||||
|     {:else if $josmState === "OK"} | ||||
|       <Tr cls="thanks shrink-0 w-fit" t={t.josmOpened} /> | ||||
|     {:else} | ||||
|       <Tr cls="alert shrink-0 w-fit" t={t.josmNotOpened} /> | ||||
|     {/if} | ||||
|   </div> | ||||
| 
 | ||||
|   <button class="flex items-center" on:click={openJosm}> | ||||
|     <Josm_logo class="h-12 w-12 p-2 pr-4" /> | ||||
|     <Tr t={t.editJosm} /> | ||||
|   </button> | ||||
| {/if} | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ | |||
|   } | ||||
| </script> | ||||
| 
 | ||||
| <button on:click={share} class="secondary m-0 h-8 w-8 p-0" use:ariaLabel={Translations.t.general.share}> | ||||
| <button on:click={share} class="soft m-0 h-8 w-8 p-0" use:ariaLabel={Translations.t.general.share}> | ||||
|   <slot name="content"> | ||||
|     <Share class="h-7 w-7 p-1" /> | ||||
|   </slot> | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
|   import Tr from "../Base/Tr.svelte" | ||||
|   import Mapillary_black from "../../assets/svg/Mapillary_black.svelte" | ||||
|   import { Mapillary } from "../../Logic/ImageProviders/Mapillary" | ||||
|   import { twMerge } from "tailwind-merge" | ||||
| 
 | ||||
|   /* | ||||
|       A subtleButton which opens mapillary in a new tab at the current location | ||||
|  | @ -16,12 +17,17 @@ | |||
|   let location = mapProperties.location | ||||
|   let zoom = mapProperties.zoom | ||||
|   let mapillaryLink = Mapillary.createLink($location, $zoom) | ||||
|   export let large: boolean = true | ||||
| </script> | ||||
| 
 | ||||
| <a class="button flex items-center" href={mapillaryLink} target="_blank"> | ||||
|   <Mapillary_black class="m-2 mr-4 h-12 w-12 shrink-0" /> | ||||
|   <div class="flex flex-col"> | ||||
| <a class="flex items-center" href={mapillaryLink} target="_blank"> | ||||
|   <Mapillary_black class={twMerge("shrink-0",large ? "m-2 mr-4 h-12 w-12" : "w-6 h-6 pr-2")} /> | ||||
|   {#if large} | ||||
|     <div class="flex flex-col"> | ||||
|       <Tr t={Translations.t.general.attribution.openMapillary} /> | ||||
|       <Tr cls="subtle" t={Translations.t.general.attribution.mapillaryHelp} /> | ||||
|     </div> | ||||
|   {:else} | ||||
|     <Tr t={Translations.t.general.attribution.openMapillary} /> | ||||
|     <Tr cls="subtle" t={Translations.t.general.attribution.mapillaryHelp} /> | ||||
|   </div> | ||||
|   {/if} | ||||
| </a> | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ | |||
|   }/${$location?.lon ?? 0}` | ||||
| </script> | ||||
| 
 | ||||
| <a class="button flex items-center" target="_blank" href={idLink}> | ||||
|   <PencilIcon class="h-12 w-12 p-2 pr-4" /> | ||||
| <a class="flex items-center" target="_blank" href={idLink}> | ||||
|   <PencilIcon class="h-6 w-6 pr-2" /> | ||||
|   <Tr t={Translations.t.general.attribution.editId} /> | ||||
| </a> | ||||
|  |  | |||
|  | @ -4,6 +4,9 @@ | |||
| import Motion from "../../Sensors/Motion" | ||||
| import { Geocoding } from "../../Logic/Osm/Geocoding" | ||||
| import type { MapProperties } from "../../Models/MapProperties" | ||||
| import Hotkeys from "../Base/Hotkeys" | ||||
| import Translations from "../i18n/Translations" | ||||
| import Locale from "../i18n/Locale" | ||||
| 
 | ||||
| export let mapProperties: MapProperties | ||||
| let lastDisplayed: Date = undefined | ||||
|  | @ -14,32 +17,36 @@ async function displayLocation() { | |||
|   let result = await Geocoding.reverse( | ||||
|     mapProperties.location.data, | ||||
|     mapProperties.zoom.data, | ||||
|     Locale.language.data | ||||
|   ) | ||||
|   console.log("Got result", result) | ||||
|   let properties = result.features[0].properties | ||||
|   currentLocation = properties.display_name | ||||
|   window.setTimeout(() => { | ||||
|     if(properties.display_name !== currentLocation){ | ||||
|       return | ||||
|     } | ||||
|     currentLocation = undefined | ||||
|   }, 5000) | ||||
| } | ||||
| 
 | ||||
| Motion.singleton.lastShakeEvent.addCallbackD(shaken => { | ||||
|   console.log("Got a shaken event") | ||||
|   if (shaken.getTime() - lastDisplayed.getTime() < 1000) { | ||||
|     console.log("To soon:",shaken.getTime() - lastDisplayed.getTime()) | ||||
|    // return | ||||
|   if (lastDisplayed !== undefined && shaken.getTime() - lastDisplayed.getTime() < 2000) { | ||||
|     return | ||||
|   } | ||||
|   displayLocation() | ||||
| }) | ||||
| Hotkeys.RegisterHotkey({ nomod: "q" }, | ||||
|   Translations.t.hotkeyDocumentation.queryCurrentLocation, | ||||
|   () => { | ||||
|     displayLocation() | ||||
|   }) | ||||
| 
 | ||||
| 
 | ||||
| Motion.singleton.startListening() | ||||
| mapProperties.location.stabilized(500).addCallbackAndRun(loc => { | ||||
|   displayLocation() | ||||
| }) | ||||
| </script> | ||||
| 
 | ||||
| {#if currentLocation} | ||||
|   <div role="alert" aria-live="assertive" class="normal-background"> | ||||
|   <div role="alert" aria-live="assertive" class="normal-background rounded-full border-interactive px-2"> | ||||
|     {currentLocation} | ||||
|   </div> | ||||
| {/if} | ||||
|  |  | |||
|  | @ -55,7 +55,7 @@ | |||
| 
 | ||||
|     <button on:click={() => state.selectedElement.setData(undefined)} | ||||
|             use:ariaLabel={Translations.t.general.backToMap} | ||||
|             class="border-none p-0"> | ||||
|             class="border-none p-0 rounded-full"> | ||||
|       <XCircleIcon aria-hidden={true} class="h-8 w-8" /> | ||||
|     </button> | ||||
|   </div> | ||||
|  |  | |||
|  | @ -7,10 +7,14 @@ | |||
|   import ThemeViewState from "../../Models/ThemeViewState" | ||||
|   import Summary from "./Summary.svelte" | ||||
|   import Tr from "../Base/Tr.svelte" | ||||
|   import { UIEventSource } from "../../Logic/UIEventSource" | ||||
|   import { Store, UIEventSource } from "../../Logic/UIEventSource" | ||||
|   import type { KeyNavigationEvent } from "../../Models/MapProperties" | ||||
|   import type { Feature } from "geojson" | ||||
| 
 | ||||
|   export let state: ThemeViewState | ||||
|   export let featuresInViewPort: Store<Feature[]> | ||||
|   console.log("Visual feedback panel:", featuresInViewPort) | ||||
|   const t = Translations.t.general.visualFeedback | ||||
|   let centerFeatures = state.closestFeatures.features | ||||
| 
 | ||||
|   let lastAction: UIEventSource<KeyNavigationEvent> = new UIEventSource<KeyNavigationEvent>(undefined) | ||||
|  | @ -22,12 +26,12 @@ | |||
| <div aria-live="assertive" class="p-1" role="alert"> | ||||
| 
 | ||||
|   {#if $lastAction !== undefined} | ||||
|     <Tr t={Translations.t.general.visualFeedback[$lastAction.key]} /> | ||||
|     <Tr t={t[$lastAction.key]} /> | ||||
|   {:else if $centerFeatures.length === 0} | ||||
|     <Tr t={Translations.t.general.visualFeedback.noCloseFeatures} /> | ||||
|     <Tr t={t.noCloseFeatures} /> | ||||
|   {:else} | ||||
|     <div class="pointer-events-auto"> | ||||
|       <Tr t={Translations.t.general.visualFeedback.closestFeaturesAre} /> | ||||
|       <Tr t={t.closestFeaturesAre.Subs({n: $featuresInViewPort?.length})} /> | ||||
|       <ol class="list-none"> | ||||
|         {#each $centerFeatures as feat, i (feat.properties.id)} | ||||
|           <li class="flex"> | ||||
|  |  | |||
|  | @ -41,7 +41,6 @@ | |||
|       return | ||||
|     } | ||||
|     altmap.data.resize() | ||||
|     const { lon, lat } = placedOverMapProperties.location.data | ||||
|     const altMapCenter = pixelCenterOf(altmap) | ||||
|     const c = placedOverMap.data.unproject(altMapCenter) | ||||
|     altproperties.location.setData({ lon: c.lng, lat: c.lat }) | ||||
|  |  | |||
|  | @ -429,7 +429,7 @@ class LineRenderingLayer { | |||
| } | ||||
| 
 | ||||
| export default class ShowDataLayer { | ||||
|     private static rangeLayer = new LayerConfig(<any>range_layer, "ShowDataLayer.ts:range.json") | ||||
|     public static rangeLayer = new LayerConfig(<any>range_layer, "ShowDataLayer.ts:range.json") | ||||
|     private readonly _options: ShowDataLayerOptions & { | ||||
|         layer: LayerConfig | ||||
|         drawMarkers?: true | boolean | ||||
|  |  | |||
|  | @ -677,6 +677,7 @@ This list will be sorted | |||
|         /* We calculate the ranges when it is opened! */ | ||||
|         return { startingMonday: lastMonday, ranges: OH.GetRanges(oh, lastMonday, nextSunday) } | ||||
|     } | ||||
| 
 | ||||
|     public static weekdaysIdentical(openingRanges: OpeningRange[][], startday = 0, endday = 4) { | ||||
|         console.log("Checking identical:", openingRanges) | ||||
|         const monday = openingRanges[startday] | ||||
|  | @ -928,21 +929,6 @@ export class ToTextualDescription { | |||
|             return t.all_days_from.Subs({ ranges: ToTextualDescription.createRangesFor(ranges[0]) }) | ||||
|         } | ||||
| 
 | ||||
|         if (OH.weekdaysIdentical(ranges, 0, 4) && OH.weekdaysIdentical(ranges, 5, 6)) { | ||||
|             let result = [] | ||||
|             if (ranges[0].length > 0) { | ||||
|                 result.push( | ||||
|                     t.on_weekdays.Subs({ ranges: ToTextualDescription.createRangesFor(ranges[0]) }) | ||||
|                 ) | ||||
|             } | ||||
|             if (ranges[6].length > 0) { | ||||
|                 result.push( | ||||
|                     t.on_weekdays.Subs({ ranges: ToTextualDescription.createRangesFor(ranges[5]) }) | ||||
|                 ) | ||||
|             } | ||||
|             return ToTextualDescription.chain(result) | ||||
|         } | ||||
| 
 | ||||
|         const result: Translation[] = [] | ||||
|         const weekdays = [ | ||||
|             "monday", | ||||
|  | @ -953,14 +939,33 @@ export class ToTextualDescription { | |||
|             "saturday", | ||||
|             "sunday", | ||||
|         ] | ||||
|         for (let i = 0; i < weekdays.length; i++) { | ||||
|             const day = weekdays[i] | ||||
|             if (ranges[i]?.length > 0) { | ||||
|                 result.push( | ||||
|                     t[day].Subs({ ranges: ToTextualDescription.createRangesFor(ranges[i]) }) | ||||
|                 ) | ||||
| 
 | ||||
|         function addRange(start: number, end: number) { | ||||
|             for (let i = start; i <= end; i++) { | ||||
|                 const day = weekdays[i] | ||||
|                 if (ranges[i]?.length > 0) { | ||||
|                     result.push( | ||||
|                         t[day].Subs({ ranges: ToTextualDescription.createRangesFor(ranges[i]) }) | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (OH.weekdaysIdentical(ranges, 0, 4)) { | ||||
|             result.push( | ||||
|                 t.on_weekdays.Subs({ ranges: ToTextualDescription.createRangesFor(ranges[0]) }) | ||||
|             ) | ||||
|         } else { | ||||
|             addRange(0, 4) | ||||
|         } | ||||
| 
 | ||||
|         if (OH.weekdaysIdentical(ranges, 5, 6)) { | ||||
|             result.push( | ||||
|                 t.on_weekdays.Subs({ ranges: ToTextualDescription.createRangesFor(ranges[5]) }) | ||||
|             ) | ||||
|         } else { | ||||
|             addRange(5, 6) | ||||
|         } | ||||
|         return ToTextualDescription.chain(result) | ||||
|     } | ||||
| 
 | ||||
|  | @ -972,6 +977,7 @@ export class ToTextualDescription { | |||
|         } | ||||
|         return tr | ||||
|     } | ||||
| 
 | ||||
|     private static timeString(date: Date) { | ||||
|         return OH.hhmm(date.getHours(), date.getMinutes()) | ||||
|     } | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ | |||
|       <HeartSolidIcon aria-hidden={true} /> | ||||
|     </button> | ||||
|   {:else} | ||||
|     <button class="p-0 m-0 h-8 w-8 no-image-background" on:click={() => markFavourite(true)} | ||||
|     <button class="p-0 m-0 h-8 w-8 no-image-background soft" on:click={() => markFavourite(true)} | ||||
|             use:ariaLabel={Translations.t.favouritePoi.button.isNotMarkedShort}> | ||||
|       <HeartOutlineIcon aria-hidden={true} /> | ||||
|     </button> | ||||
|  |  | |||
|  | @ -17,7 +17,6 @@ | |||
|   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" | ||||
|  | @ -54,7 +53,6 @@ | |||
|   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" | ||||
|  | @ -66,6 +64,11 @@ | |||
|   import Compass_arrow from "../assets/svg/Compass_arrow.svelte" | ||||
|   import ReverseGeocoding from "./BigComponents/ReverseGeocoding.svelte" | ||||
|   import FilterPanel from "./BigComponents/FilterPanel.svelte" | ||||
|   import PrivacyPolicy from "./BigComponents/PrivacyPolicy.svelte" | ||||
|   import { BBox } from "../Logic/BBox" | ||||
|   import { GeoOperations } from "../Logic/GeoOperations" | ||||
|   import ShowDataLayer from "./Map/ShowDataLayer" | ||||
|   import StaticFeatureSource from "../Logic/FeatureSource/Sources/StaticFeatureSource" | ||||
| 
 | ||||
|   export let state: ThemeViewState | ||||
|   let layout = state.layout | ||||
|  | @ -100,8 +103,30 @@ | |||
|   ) | ||||
|   let currentZoom = state.mapProperties.zoom | ||||
|   let showCrosshair = state.userRelatedState.showCrosshair | ||||
|   let arrowKeysWereUsed = state.visualFeedback | ||||
|   let centerFeatures = state.closestFeatures.features | ||||
|   let visualFeedback = state.visualFeedback | ||||
|   let viewport: UIEventSource<HTMLDivElement> = new UIEventSource<HTMLDivElement>(undefined) | ||||
|   let featuresInViewPort: UIEventSource<Feature[]> = new UIEventSource<Feature[]>(undefined) | ||||
|   viewport.addCallbackAndRunD(viewport => { | ||||
|     state.featuresInView.features.addCallbackAndRunD((features: Feature[]) => { | ||||
|       const rect = viewport.getBoundingClientRect() | ||||
|       const mlmap = state.map.data | ||||
|       if (!mlmap) { | ||||
|         return undefined | ||||
|       } | ||||
|       const topLeft = mlmap.unproject([rect.left, rect.top]) | ||||
|       const bottomRight = mlmap.unproject([rect.right, rect.bottom]) | ||||
|       const bbox = new BBox([[topLeft.lng, topLeft.lat], [bottomRight.lng, bottomRight.lat]]) | ||||
|       const bboxGeo = bbox.asGeoJson({}) | ||||
|       console.log("BBOX:", bboxGeo) | ||||
|        | ||||
|       const filtered = features.filter((f: Feature) => { | ||||
|         console.log(f, bboxGeo) | ||||
|         return GeoOperations.calculateOverlap(bboxGeo, [f]).length > 0 | ||||
|       }) | ||||
|       featuresInViewPort.setData(filtered) | ||||
|     }) | ||||
| 
 | ||||
|   }) | ||||
|   let mapproperties: MapProperties = state.mapProperties | ||||
|   let featureSwitches: FeatureSwitchState = state.featureSwitches | ||||
|   let availableLayers = state.availableLayers | ||||
|  | @ -133,6 +158,13 @@ | |||
|   <MaplibreMap map={maplibremap} /> | ||||
| </div> | ||||
| 
 | ||||
| {#if $visualFeedback} | ||||
|   <div class="absolute top-0 left-0 h-screen w-screen overflow-hidden flex items-center justify-center"> | ||||
| 
 | ||||
|     <div bind:this={$viewport} style="border: 2px solid #ff000044; width: 300px; height: 300px"></div> | ||||
|   </div> | ||||
| {/if} | ||||
| 
 | ||||
| <div class="pointer-events-none absolute top-0 left-0 w-full"> | ||||
|   <!-- Top components --> | ||||
|   <If condition={state.featureSwitches.featureSwitchSearch}> | ||||
|  | @ -183,7 +215,7 @@ | |||
|       <div class="alert w-fit">Testmode</div> | ||||
|     </If> | ||||
|   </div> | ||||
|   <div class="flex w-full justify-center"> | ||||
|   <div class="flex flex-col w-full justify-center items-center"> | ||||
|     <!-- Flex and w-full are needed for the positioning --> | ||||
|     <!-- Centermessage --> | ||||
|     <StateIndicator {state} /> | ||||
|  | @ -238,7 +270,7 @@ | |||
|       </div> | ||||
|     </div> | ||||
|     <If condition={state.visualFeedback}> | ||||
|       <VisualFeedbackPanel {state} /> | ||||
|       <VisualFeedbackPanel {state} {featuresInViewPort} /> | ||||
|     </If> | ||||
| 
 | ||||
|     <div class="flex flex-col items-end"> | ||||
|  | @ -265,7 +297,7 @@ | |||
|         <Min class="h-8 w-8" /> | ||||
|       </MapControlButton> | ||||
|       <If condition={featureSwitches.featureSwitchGeolocation}> | ||||
|         <div class="relative m-0.5 md:m-1"> | ||||
|         <div class="relative m-0"> | ||||
|           <MapControlButton arialabel={Translations.t.general.labels.jumpToLocation} | ||||
|                             on:click={() => state.geolocationControl.handleClick()} | ||||
|                             on:keydown={forwardEventToMap} | ||||
|  | @ -288,7 +320,7 @@ | |||
| 
 | ||||
| 
 | ||||
| <LoginToggle ignoreLoading={true} {state}> | ||||
|   {#if ($showCrosshair === "yes" && $currentZoom >= 17) || $showCrosshair === "always" || $arrowKeysWereUsed} | ||||
|   {#if ($showCrosshair === "yes" && $currentZoom >= 17) || $showCrosshair === "always" || $visualFeedback} | ||||
|     <div | ||||
|       class="pointer-events-none absolute top-0 left-0 flex h-full w-full items-center justify-center" | ||||
|     > | ||||
|  | @ -416,6 +448,7 @@ | |||
|   </FloatOver> | ||||
| </IfHidden> | ||||
| 
 | ||||
| 
 | ||||
| <If condition={state.guistate.menuIsOpened}> | ||||
|   <!-- Menu page --> | ||||
|   <FloatOver on:close={() => state.guistate.menuIsOpened.setData(false)}> | ||||
|  | @ -458,10 +491,27 @@ | |||
|           <Tr t={Translations.t.general.attribution.donate} /> | ||||
|         </a> | ||||
| 
 | ||||
|         <a class="flex" href={Utils.OsmChaLinkFor(7)} target="_blank"> | ||||
|           <Statistics class="h-6 w-6" /> | ||||
|           <Tr t={Translations.t.general.attribution.openOsmcha.Subs({ theme: "MapComplete" })} /> | ||||
|         </a> | ||||
|         <button class="small soft flex" on:click={() => state.guistate.communityIndexPanelIsOpened.setData(true)}> | ||||
|           <Community class="h-6 w-6" /> | ||||
|           <Tr t={Translations.t.communityIndex.title} /> | ||||
|         </button> | ||||
| 
 | ||||
| 
 | ||||
|         <If condition={featureSwitches.featureSwitchEnableLogin}> | ||||
|           <OpenIdEditor mapProperties={state.mapProperties} /> | ||||
|           <OpenJosm {state} /> | ||||
|           <MapillaryLink large={false} mapProperties={state.mapProperties} /> | ||||
|         </If> | ||||
| 
 | ||||
|         <button class="small soft flex" | ||||
|                 on:click={() => state.guistate.privacyPanelIsOpened.setData(true)} | ||||
|         > | ||||
|           <EyeIcon class="w-6 h-6 pr-1" /> | ||||
|           <Tr t={Translations.t.privacy.title} /> | ||||
|         </button> | ||||
|         <div class="m-2 flex flex-col"> | ||||
|           <ToSvelte construct={Hotkeys.generateDocumentationDynamic} /> | ||||
|         </div> | ||||
|         {Constants.vNumber} | ||||
|       </div> | ||||
| 
 | ||||
|  | @ -503,31 +553,40 @@ | |||
|         </h3> | ||||
|         <Favourites {state} /> | ||||
|       </div> | ||||
|       <div class="flex" slot="title3"> | ||||
|         <Community class="h-6 w-6" /> | ||||
|         <Tr t={Translations.t.communityIndex.title} /> | ||||
|       </div> | ||||
|       <div class="m-2" slot="content3"> | ||||
|         <CommunityIndexView location={state.mapProperties.location} /> | ||||
|       </div> | ||||
|       <div class="flex" slot="title4"> | ||||
|         <EyeIcon class="w-6" /> | ||||
|         <Tr t={Translations.t.privacy.title} /> | ||||
|       </div> | ||||
|       <div class="m-2" slot="content4"> | ||||
|         <ToSvelte construct={() => new PrivacyPolicy()} /> | ||||
|       </div> | ||||
| 
 | ||||
|       <Tr slot="title5" t={Translations.t.advanced.title} /> | ||||
|       <div class="m-2 flex flex-col" slot="content5"> | ||||
|         <If condition={featureSwitches.featureSwitchEnableLogin}> | ||||
|           <OpenIdEditor mapProperties={state.mapProperties} /> | ||||
|           <OpenJosm {state} /> | ||||
|           <MapillaryLink mapProperties={state.mapProperties} /> | ||||
|         </If> | ||||
| 
 | ||||
|         <ToSvelte construct={Hotkeys.generateDocumentationDynamic} /> | ||||
|       </div> | ||||
|     </TabbedGroup> | ||||
|   </FloatOver> | ||||
| </If> | ||||
| 
 | ||||
| <If condition={state.guistate.privacyPanelIsOpened}> | ||||
|   <FloatOver on:close={() => state.guistate.privacyPanelIsOpened.setData(false)}> | ||||
|     <div class="h-full flex flex-col overflow-hidden"> | ||||
|       <h2 class="flex items-center low-interaction p-4 m-0"> | ||||
|         <EyeIcon class="w-6 pr-2" /> | ||||
|         <Tr t={Translations.t.privacy.title} /> | ||||
|       </h2> | ||||
|       <div class="overflow-auto p-4"> | ||||
|         <PrivacyPolicy /> | ||||
|       </div> | ||||
|     </div> | ||||
|   </FloatOver> | ||||
| </If> | ||||
| 
 | ||||
| 
 | ||||
| <If condition={state.guistate.communityIndexPanelIsOpened}> | ||||
|   <FloatOver on:close={() => state.guistate.communityIndexPanelIsOpened.setData(false)}> | ||||
|     <div class="h-full flex flex-col overflow-hidden"> | ||||
|       <h2 class="flex items-center low-interaction p-4 m-0"> | ||||
|         <Community class="h-6 w-6" /> | ||||
|         <Tr t={Translations.t.communityIndex.title} /> | ||||
|       </h2> | ||||
|       <div class="overflow-auto p-4"> | ||||
|         <CommunityIndexView location={state.mapProperties.location} /> | ||||
|       </div> | ||||
|     </div> | ||||
| 
 | ||||
| 
 | ||||
|   </FloatOver> | ||||
| </If> | ||||
| 
 | ||||
|  |  | |||
|  | @ -350,6 +350,11 @@ label.checked:not(.neutral-label) { | |||
|     width: 100%; | ||||
| } | ||||
| 
 | ||||
| button.soft, .button.soft { | ||||
|     border: 2px solid var(--interactive-background); | ||||
|     margin: 0; | ||||
| } | ||||
| 
 | ||||
| .links-as-button a { | ||||
|     /* | ||||
|     * Let a 'link' mimick a button, but not entirely | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue