forked from MapComplete/MapComplete
		
	chore: automated housekeeping...
This commit is contained in:
		
							parent
							
								
									c10fecb7e8
								
							
						
					
					
						commit
						f5d7686c98
					
				
					 234 changed files with 3493 additions and 2482 deletions
				
			
		|  | @ -102,7 +102,11 @@ | |||
|       </div> | ||||
|     </div> | ||||
| 
 | ||||
|     <Searchbar value={themeSearchText} placeholder={tr.searchForATheme} on:search={() => MoreScreen.applySearch(themeSearchText.data)}/> | ||||
|     <Searchbar | ||||
|       value={themeSearchText} | ||||
|       placeholder={tr.searchForATheme} | ||||
|       on:search={() => MoreScreen.applySearch(themeSearchText.data)} | ||||
|     /> | ||||
| 
 | ||||
|     <ThemesList search={themeSearchText} {state} themes={MoreScreen.officialThemes} /> | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,28 +3,27 @@ | |||
|   import { sineIn } from "svelte/easing" | ||||
|   import { UIEventSource } from "../../Logic/UIEventSource.js" | ||||
| 
 | ||||
|   export let shown: UIEventSource<boolean>; | ||||
|   export let shown: UIEventSource<boolean> | ||||
|   let transitionParams = { | ||||
|     x: -320, | ||||
|     duration: 200, | ||||
|     easing: sineIn | ||||
|   }; | ||||
|     easing: sineIn, | ||||
|   } | ||||
|   let hidden = !shown.data | ||||
|   $: { | ||||
|     shown.setData(!hidden) | ||||
|   } | ||||
|   shown.addCallback(sh => { | ||||
|   shown.addCallback((sh) => { | ||||
|     hidden = !sh | ||||
|   }) | ||||
| </script> | ||||
| 
 | ||||
| 
 | ||||
| <Drawer placement="left" | ||||
|         transitionType="fly" {transitionParams} | ||||
|         divClass = "overflow-y-auto z-50 " | ||||
|         bind:hidden={hidden}> | ||||
|   <slot> | ||||
|     CONTENTS | ||||
|   </slot> | ||||
| <Drawer | ||||
|   placement="left" | ||||
|   transitionType="fly" | ||||
|   {transitionParams} | ||||
|   divClass="overflow-y-auto z-50 " | ||||
|   bind:hidden | ||||
| > | ||||
|   <slot>CONTENTS</slot> | ||||
| </Drawer> | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ | |||
|   }} | ||||
| > | ||||
|   <div | ||||
|     class="content relative normal-background pointer-events-auto h-full" | ||||
|     class="content normal-background pointer-events-auto relative h-full" | ||||
|     on:click|stopPropagation={() => {}} | ||||
|   > | ||||
|     <div class="h-full rounded-xl"> | ||||
|  | @ -39,20 +39,16 @@ | |||
|     <slot name="close-button"> | ||||
|       <!-- The close button is placed _after_ the default slot in order to always paint it on top --> | ||||
|       <div class="absolute top-0 right-0"> | ||||
| 
 | ||||
|         <CloseButton class="normal-background mt-2 mr-2" | ||||
|                      on:click={() => dispatch("close")} | ||||
|         /> | ||||
|         <CloseButton class="normal-background mt-2 mr-2" on:click={() => dispatch("close")} /> | ||||
|       </div> | ||||
| 
 | ||||
|     </slot> | ||||
|   </div> | ||||
| </div> | ||||
| 
 | ||||
| <style> | ||||
|     .content { | ||||
|         border-radius: 0.5rem; | ||||
|         overflow-x: hidden; | ||||
|         box-shadow: 0 0 1rem #00000088; | ||||
|     } | ||||
|   .content { | ||||
|     border-radius: 0.5rem; | ||||
|     overflow-x: hidden; | ||||
|     box-shadow: 0 0 1rem #00000088; | ||||
|   } | ||||
| </style> | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ | |||
|   export let text: string | ||||
|   export let href: string | ||||
| 
 | ||||
| 
 | ||||
|   export let classnames: string = undefined | ||||
|   export let download: string = undefined | ||||
|   export let ariaLabel: string = undefined | ||||
|  | @ -13,7 +12,7 @@ | |||
| </script> | ||||
| 
 | ||||
| <a | ||||
|   href={Utils.prepareHref(href) } | ||||
|   href={Utils.prepareHref(href)} | ||||
|   aria-label={ariaLabel} | ||||
|   title={ariaLabel} | ||||
|   target={newTab ? "_blank" : undefined} | ||||
|  |  | |||
|  | @ -14,6 +14,6 @@ | |||
|     osmConnection.LogOut() | ||||
|   }} | ||||
| > | ||||
|   <ArrowRightOnRectangle class="h-6 w-6 max-h-full" /> | ||||
|   <ArrowRightOnRectangle class="h-6 max-h-full w-6" /> | ||||
|   <Tr t={Translations.t.general.logout} /> | ||||
| </button> | ||||
|  |  | |||
|  | @ -14,7 +14,6 @@ | |||
|   export let arialabel: Translation = undefined | ||||
|   export let arialabelDynamic: Store<Translation> = new ImmutableStore(arialabel) | ||||
|   let arialabelString = arialabelDynamic.bind((tr) => tr?.current) | ||||
| 
 | ||||
| </script> | ||||
| 
 | ||||
| <button | ||||
|  |  | |||
|  | @ -6,12 +6,13 @@ | |||
|   export let shown: UIEventSource<boolean> | ||||
|   let _shown = false | ||||
|   export let onlyLink: boolean = false | ||||
|   shown.addCallbackAndRun(sh => { | ||||
|   shown.addCallbackAndRun((sh) => { | ||||
|     _shown = sh | ||||
|   }) | ||||
|   export let fullscreen: boolean = false | ||||
| 
 | ||||
|   const shared = "in-page normal-background dark:bg-gray-800 rounded-lg border-gray-200 dark:border-gray-700 border-gray-200 dark:border-gray-700 divide-gray-200 dark:divide-gray-700 shadow-md" | ||||
|   const shared = | ||||
|     "in-page normal-background dark:bg-gray-800 rounded-lg border-gray-200 dark:border-gray-700 border-gray-200 dark:border-gray-700 divide-gray-200 dark:divide-gray-700 shadow-md" | ||||
|   let defaultClass = "relative flex flex-col mx-auto w-full divide-y " + shared | ||||
|   if (fullscreen) { | ||||
|     defaultClass = shared | ||||
|  | @ -21,14 +22,21 @@ | |||
|     dialogClass += " h-full-child" | ||||
|   } | ||||
|   let bodyClass = "h-full p-4 md:p-5 space-y-4 flex-1 overflow-y-auto overscroll-contain" | ||||
|   let headerClass = "flex justify-between items-center p-2 px-4 md:px-5 rounded-t-lg"; | ||||
|   let headerClass = "flex justify-between items-center p-2 px-4 md:px-5 rounded-t-lg" | ||||
| </script> | ||||
| 
 | ||||
| {#if !onlyLink} | ||||
|   <Modal open={_shown} on:close={() => shown.set(false)} outsideclose | ||||
|          size="xl" | ||||
|          {defaultClass} {bodyClass} {dialogClass} {headerClass} | ||||
|          color="none"> | ||||
|   <Modal | ||||
|     open={_shown} | ||||
|     on:close={() => shown.set(false)} | ||||
|     outsideclose | ||||
|     size="xl" | ||||
|     {defaultClass} | ||||
|     {bodyClass} | ||||
|     {dialogClass} | ||||
|     {headerClass} | ||||
|     color="none" | ||||
|   > | ||||
|     <h1 slot="header" class="page-header w-full"> | ||||
|       <slot name="header" /> | ||||
|     </h1> | ||||
|  | @ -40,20 +48,20 @@ | |||
| {:else} | ||||
|   <button class="as-link sidebar-button" on:click={() => shown.setData(true)}> | ||||
|     <slot name="link"> | ||||
|     <slot name="header" /> | ||||
|       <slot name="header" /> | ||||
|     </slot> | ||||
|   </button> | ||||
| {/if} | ||||
| 
 | ||||
| <style> | ||||
|     :global(.page-header) { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|     } | ||||
|   :global(.page-header) { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|   } | ||||
| 
 | ||||
|   :global(.page-header svg) { | ||||
|       width: 2rem; | ||||
|       height: 2rem; | ||||
|       margin-right: 0.75rem; | ||||
|     width: 2rem; | ||||
|     height: 2rem; | ||||
|     margin-right: 0.75rem; | ||||
|   } | ||||
| </style> | ||||
|  |  | |||
|  | @ -9,35 +9,30 @@ | |||
| 
 | ||||
|   export let value: UIEventSource<string> | ||||
|   let _value = value.data ?? "" | ||||
|   value.addCallbackD(v => { | ||||
|   value.addCallbackD((v) => { | ||||
|     _value = v | ||||
|   }) | ||||
|   $: value.set(_value) | ||||
| 
 | ||||
|   const dispatch = createEventDispatcher<{ search }>() | ||||
|   export let placeholder: Translation =  Translations.t.general.search.search | ||||
|   export let placeholder: Translation = Translations.t.general.search.search | ||||
| </script> | ||||
| 
 | ||||
| 
 | ||||
| <form | ||||
|   class="flex justify-center" | ||||
|   on:submit|preventDefault={() => dispatch("search")} | ||||
| > | ||||
| <form class="flex justify-center" on:submit|preventDefault={() => dispatch("search")}> | ||||
|   <label | ||||
|     class="neutral-label my-2 flex w-full items-center rounded-full border-2 border-black sm:w-1/2  box-shadow" | ||||
|     class="neutral-label box-shadow my-2 flex w-full items-center rounded-full border-2 border-black sm:w-1/2" | ||||
|   > | ||||
|     <input | ||||
|       type="search" | ||||
|       style=" --tw-ring-color: rgb(0 0 0 / 0) !important;" | ||||
|       class="ml-4 pl-1 w-full outline-none border-none" | ||||
|       class="ml-4 w-full border-none pl-1 outline-none" | ||||
|       on:keypress={(keypr) => { | ||||
|           return keypr.key === "Enter" ? dispatch("search") : undefined | ||||
|         }} | ||||
|         return keypr.key === "Enter" ? dispatch("search") : undefined | ||||
|       }} | ||||
|       bind:value={_value} | ||||
|       use:set_placeholder={placeholder} | ||||
|       use:ariaLabel={Translations.t.general.search.search} | ||||
|     /> | ||||
|     <SearchIcon aria-hidden="true" class="h-8 w-8 mx-2" /> | ||||
| 
 | ||||
|     <SearchIcon aria-hidden="true" class="mx-2 h-8 w-8" /> | ||||
|   </label> | ||||
| </form> | ||||
|  |  | |||
|  | @ -7,6 +7,5 @@ | |||
|     <slot /> | ||||
|   </div> | ||||
| 
 | ||||
| 
 | ||||
|   <slot class="border-t-gray-300 mt-1" name="footer" /> | ||||
|   <slot class="mt-1 border-t-gray-300" name="footer" /> | ||||
| </div> | ||||
|  |  | |||
|  | @ -14,7 +14,6 @@ | |||
|     const license: SmallLicense = licenses[key] | ||||
|     allLicenses[license.path] = license | ||||
|   } | ||||
| 
 | ||||
| </script> | ||||
| 
 | ||||
| {#each iconAttributions as iconAttribution} | ||||
|  |  | |||
|  | @ -20,7 +20,6 @@ | |||
|   const t = Translations.t.general.attribution | ||||
|   const layoutToUse = state.layout | ||||
| 
 | ||||
| 
 | ||||
|   let maintainer: Translation = undefined | ||||
|   if (layoutToUse.credits !== undefined && layoutToUse.credits !== "") { | ||||
|     maintainer = t.themeBy.Subs({ author: layoutToUse.credits }) | ||||
|  | @ -48,8 +47,6 @@ | |||
|     return Translations.t.general.attribution.attributionBackgroundLayer.Subs(props) | ||||
|   }) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|   function calculateDataContributions(contributions: Map<string, number>): Translation { | ||||
|     if (contributions === undefined) { | ||||
|       return undefined | ||||
|  | @ -147,7 +144,6 @@ | |||
|     <Tr t={codeContributors(translators, t.translatedBy)} /> | ||||
|   </div> | ||||
| 
 | ||||
| 
 | ||||
|   <div class="self-end"> | ||||
|     MapComplete {Constants.vNumber} | ||||
|   </div> | ||||
|  |  | |||
|  | @ -107,14 +107,14 @@ | |||
| </script> | ||||
| 
 | ||||
| <div class="normal-background flex justify-between rounded-full pl-2"> | ||||
|   <form class="flex w-full flex-wrap items-center "> | ||||
|   <form class="flex w-full flex-wrap items-center"> | ||||
|     {#if isRunning} | ||||
|       <Loading>{Translations.t.general.search.searching}</Loading> | ||||
|     {:else} | ||||
|       <input | ||||
|         type="search" | ||||
|         style="border: none !important;" | ||||
|         class="w-full outline-none border-none mx-2" | ||||
|         class="mx-2 w-full border-none outline-none" | ||||
|         bind:this={inputElement} | ||||
|         on:keypress={(keypr) => { | ||||
|           feedback = undefined | ||||
|  | @ -132,5 +132,5 @@ | |||
|       {/if} | ||||
|     {/if} | ||||
|   </form> | ||||
|   <SearchIcon aria-hidden="true" class="h-6 w-6 mx-2 self-center" on:click={performSearch} /> | ||||
|   <SearchIcon aria-hidden="true" class="mx-2 h-6 w-6 self-center" on:click={performSearch} /> | ||||
| </div> | ||||
|  |  | |||
|  | @ -15,31 +15,31 @@ | |||
|   } | ||||
| </script> | ||||
| 
 | ||||
|   <Tr t={t.intro} /> | ||||
|   <table> | ||||
| <Tr t={t.intro} /> | ||||
| <table> | ||||
|   <tr> | ||||
|     <th> | ||||
|       <Tr t={t.key} /> | ||||
|     </th> | ||||
|     <th> | ||||
|       <Tr t={t.action} /> | ||||
|     </th> | ||||
|   </tr> | ||||
|   {#each byKey as [key, doc, alsoTriggeredBy]} | ||||
|     <tr> | ||||
|       <th> | ||||
|         <Tr t={t.key} /> | ||||
|       </th> | ||||
|       <th> | ||||
|         <Tr t={t.action} /> | ||||
|       </th> | ||||
|       <td class="flex items-center justify-center"> | ||||
|         {#if alsoTriggeredBy} | ||||
|           <div class="flex items-center justify-center gap-x-1"> | ||||
|             <div class="literal-code h-fit w-fit">{key}</div> | ||||
|             <div class="literal-code h-fit w-fit">{alsoTriggeredBy}</div> | ||||
|           </div> | ||||
|         {:else} | ||||
|           <div class="literal-code flex h-fit w-fit w-full items-center">{key}</div> | ||||
|         {/if} | ||||
|       </td> | ||||
|       <td> | ||||
|         <Tr t={doc} /> | ||||
|       </td> | ||||
|     </tr> | ||||
|     {#each byKey as [key, doc, alsoTriggeredBy]} | ||||
|       <tr> | ||||
|         <td class="flex items-center justify-center"> | ||||
|           {#if alsoTriggeredBy} | ||||
|             <div class="flex items-center justify-center gap-x-1"> | ||||
|               <div class="literal-code h-fit w-fit">{key}</div> | ||||
|               <div class="literal-code h-fit w-fit">{alsoTriggeredBy}</div> | ||||
|             </div> | ||||
|           {:else} | ||||
|             <div class="literal-code flex h-fit w-fit w-full items-center">{key}</div> | ||||
|           {/if} | ||||
|         </td> | ||||
|         <td> | ||||
|           <Tr t={doc} /> | ||||
|         </td> | ||||
|       </tr> | ||||
|     {/each} | ||||
|   </table> | ||||
|   {/each} | ||||
| </table> | ||||
|  |  | |||
|  | @ -1,5 +1,4 @@ | |||
| <script lang="ts"> | ||||
| 
 | ||||
|   // All the relevant links | ||||
|   import ThemeViewState from "../../Models/ThemeViewState" | ||||
|   import Translations from "../i18n/Translations" | ||||
|  | @ -63,15 +62,19 @@ | |||
|   const t = Translations.t.general.menu | ||||
| </script> | ||||
| 
 | ||||
| <div class="flex flex-col p-2 sm:p-3 low-interaction gap-y-2 sm:gap-y-3 h-screen overflow-y-auto"> | ||||
| <div class="low-interaction flex h-screen flex-col gap-y-2 overflow-y-auto p-2 sm:gap-y-3 sm:p-3"> | ||||
|   <div class="flex justify-between"> | ||||
|     <h2> | ||||
|       <Tr t={t.title}/> | ||||
|       <Tr t={t.title} /> | ||||
|     </h2> | ||||
|     <CloseButton on:click={() => {pg.menu.set(false)}} /> | ||||
|     <CloseButton | ||||
|       on:click={() => { | ||||
|         pg.menu.set(false) | ||||
|       }} | ||||
|     /> | ||||
|   </div> | ||||
|   {#if $showHome} | ||||
|     <a class="flex button primary" href={Utils.HomepageLink()}> | ||||
|     <a class="button primary flex" href={Utils.HomepageLink()}> | ||||
|       <Squares2x2 class="h-10 w-10" /> | ||||
|       {#if Utils.isIframe} | ||||
|         <Tr t={Translations.t.general.seeIndex} /> | ||||
|  | @ -81,23 +84,21 @@ | |||
|     </a> | ||||
|   {/if} | ||||
| 
 | ||||
| 
 | ||||
|   <!-- User related: avatar, settings, favourits, logout --> | ||||
|   <div class="sidebar-unit"> | ||||
|     <LoginToggle {state}> | ||||
|       <LoginButton osmConnection={state.osmConnection} slot="not-logged-in"></LoginButton> | ||||
|       <div class="flex gap-x-4 items-center"> | ||||
|       <LoginButton osmConnection={state.osmConnection} slot="not-logged-in" /> | ||||
|       <div class="flex items-center gap-x-4"> | ||||
|         {#if $userdetails.img} | ||||
|           <img src={$userdetails.img} class="rounded-full w-14 h-14" /> | ||||
|           <img src={$userdetails.img} class="h-14 w-14 rounded-full" /> | ||||
|         {/if} | ||||
|         <b>{$userdetails.name}</b> | ||||
|       </div> | ||||
|     </LoginToggle> | ||||
| 
 | ||||
| 
 | ||||
|     <Page {onlyLink} shown={pg.usersettings}> | ||||
|       <svelte:fragment slot="header"> | ||||
|         <CogIcon/> | ||||
|         <CogIcon /> | ||||
|         <Tr t={UserRelatedState.usersettingsConfig.title.GetRenderValue({})} /> | ||||
|       </svelte:fragment> | ||||
| 
 | ||||
|  | @ -112,30 +113,24 @@ | |||
|           highlightedRendering={state.guistate.highlightedUserSetting} | ||||
|           layer={usersettingslayer} | ||||
|           selectedElement={{ | ||||
|                 type: "Feature", | ||||
|                 properties: { id: "settings" }, | ||||
|                 geometry: { type: "Point", coordinates: [0, 0] }, | ||||
|               }} | ||||
| 
 | ||||
|             type: "Feature", | ||||
|             properties: { id: "settings" }, | ||||
|             geometry: { type: "Point", coordinates: [0, 0] }, | ||||
|           }} | ||||
|           {state} | ||||
|           tags={state.userRelatedState.preferencesAsTags} | ||||
|         /> | ||||
|       </LoginToggle> | ||||
| 
 | ||||
| 
 | ||||
|     </Page> | ||||
| 
 | ||||
|     <LoginToggle {state}> | ||||
|       <Page {onlyLink} shown={pg.favourites}> | ||||
| 
 | ||||
|         <svelte:fragment slot="header"> | ||||
|           <HeartIcon /> | ||||
|           <Tr t={Translations.t.favouritePoi.tab} /> | ||||
|         </svelte:fragment> | ||||
| 
 | ||||
| 
 | ||||
|         <h3> | ||||
| 
 | ||||
|           <Tr t={Translations.t.favouritePoi.title} /> | ||||
|         </h3> | ||||
|         <div> | ||||
|  | @ -152,10 +147,8 @@ | |||
|     </LoginToggle> | ||||
| 
 | ||||
|     <LanguagePicker /> | ||||
| 
 | ||||
|   </div> | ||||
| 
 | ||||
| 
 | ||||
|   <!-- Theme related: documentation links, download, ... --> | ||||
|   <div class="sidebar-unit"> | ||||
|     <h3> | ||||
|  | @ -167,7 +160,7 @@ | |||
|         <Marker icons={layout.icon} size="h-6 w-6 mr-2" /> | ||||
|         <Tr t={t.showIntroduction} /> | ||||
|       </div> | ||||
|       <svelte:fragment  slot="header"> | ||||
|       <svelte:fragment slot="header"> | ||||
|         <Marker icons={layout.icon} /> | ||||
|         <Tr t={layout.title} /> | ||||
|       </svelte:fragment> | ||||
|  | @ -180,17 +173,16 @@ | |||
| 
 | ||||
|     <Page {onlyLink} shown={pg.share}> | ||||
|       <svelte:fragment slot="header"> | ||||
|         <Share/> | ||||
|         <Share /> | ||||
|         <Tr t={Translations.t.general.sharescreen.title} /> | ||||
|       </svelte:fragment> | ||||
|       <ShareScreen {state} /> | ||||
|     </Page> | ||||
| 
 | ||||
| 
 | ||||
|     {#if state.featureSwitches.featureSwitchEnableExport} | ||||
|       <Page {onlyLink} shown={pg.download}> | ||||
|         <svelte:fragment slot="header"> | ||||
|           <ArrowDownTray  /> | ||||
|           <ArrowDownTray /> | ||||
|           <Tr t={Translations.t.general.download.title} /> | ||||
|         </svelte:fragment> | ||||
|         <DownloadPanel {state} /> | ||||
|  | @ -201,15 +193,15 @@ | |||
|       <a | ||||
|         class="flex" | ||||
|         href={"https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Themes/" + | ||||
|         layout.id + | ||||
|         ".md"} | ||||
|           layout.id + | ||||
|           ".md"} | ||||
|         target="_blank" | ||||
|       > | ||||
|         <DocumentMagnifyingGlass class="h-6 w-6" /> | ||||
|         <Tr | ||||
|           t={Translations.t.general.attribution.openThemeDocumentation.Subs({ | ||||
|           name: layout.title, | ||||
|         })} | ||||
|             name: layout.title, | ||||
|           })} | ||||
|         /> | ||||
|       </a> | ||||
| 
 | ||||
|  | @ -220,53 +212,43 @@ | |||
|     {/if} | ||||
|   </div> | ||||
| 
 | ||||
| 
 | ||||
|   <!-- Other links and tools for the given location: open iD/JOSM; community index, ... --> | ||||
|   <div class="sidebar-unit"> | ||||
| 
 | ||||
|     <h3> | ||||
|       <Tr t={t.moreUtilsTitle} /> | ||||
|     </h3> | ||||
| 
 | ||||
| 
 | ||||
|     <Page {onlyLink} shown={pg.community_index}> | ||||
|       <svelte:fragment slot="header"> | ||||
|         <Community/> | ||||
|         <Community /> | ||||
|         <Tr t={Translations.t.communityIndex.title} /> | ||||
|       </svelte:fragment> | ||||
|       <CommunityIndexView location={state.mapProperties.location} /> | ||||
|     </Page> | ||||
| 
 | ||||
| 
 | ||||
|     <If condition={featureSwitches.featureSwitchEnableLogin}> | ||||
|       <OpenIdEditor mapProperties={state.mapProperties} /> | ||||
|       <OpenJosm {state} /> | ||||
|       <MapillaryLink large={false} mapProperties={state.mapProperties} /> | ||||
|     </If> | ||||
| 
 | ||||
|   </div> | ||||
| 
 | ||||
| 
 | ||||
|   <!-- About MC: various outward links, legal info, ... --> | ||||
|   <div class="sidebar-unit"> | ||||
| 
 | ||||
|     <h3> | ||||
|       <Tr t={Translations.t.general.menu.aboutMapComplete} /> | ||||
|     </h3> | ||||
| 
 | ||||
|     <a | ||||
|       class="flex" | ||||
|       href={window.location.protocol + "//" + window.location.host + "/studio.html"} | ||||
|     > | ||||
|     <a class="flex" 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> | ||||
| 
 | ||||
|     <div class="hidden-on-mobile w-full"> | ||||
|       <Page {onlyLink} shown={pg.hotkeys}> | ||||
|         <svelte:fragment  slot="header"> | ||||
|         <svelte:fragment slot="header"> | ||||
|           <BoltIcon /> | ||||
|           <Tr t={ Translations.t.hotkeyDocumentation.title} /> | ||||
|           <Tr t={Translations.t.hotkeyDocumentation.title} /> | ||||
|         </svelte:fragment> | ||||
|         <HotkeyTable /> | ||||
|       </Page> | ||||
|  | @ -282,7 +264,6 @@ | |||
|       <Tr t={Translations.t.general.attribution.openIssueTracker} /> | ||||
|     </a> | ||||
| 
 | ||||
| 
 | ||||
|     <a class="flex" href="https://en.osm.town/@MapComplete" target="_blank"> | ||||
|       <Mastodon class="h-6 w-6" /> | ||||
|       <Tr t={Translations.t.general.attribution.followOnMastodon} /> | ||||
|  | @ -293,7 +274,6 @@ | |||
|       <Tr t={Translations.t.general.attribution.donate} /> | ||||
|     </a> | ||||
| 
 | ||||
| 
 | ||||
|     <Page {onlyLink} shown={pg.copyright}> | ||||
|       <svelte:fragment slot="header"> | ||||
|         <Copyright /> | ||||
|  | @ -302,17 +282,14 @@ | |||
|       <CopyrightPanel {state} /> | ||||
|     </Page> | ||||
| 
 | ||||
| 
 | ||||
|     <Page {onlyLink} shown={pg.copyright_icons}> | ||||
|       <svelte:fragment slot="header" > | ||||
|         <Copyright/> | ||||
|         <Tr t={ Translations.t.general.attribution.iconAttribution.title} /> | ||||
|       <svelte:fragment slot="header"> | ||||
|         <Copyright /> | ||||
|         <Tr t={Translations.t.general.attribution.iconAttribution.title} /> | ||||
|       </svelte:fragment> | ||||
|       <CopyrightAllIcons {state} /> | ||||
| 
 | ||||
|     </Page> | ||||
| 
 | ||||
| 
 | ||||
|     <Page {onlyLink} shown={pg.privacy}> | ||||
|       <svelte:fragment slot="header"> | ||||
|         <EyeIcon /> | ||||
|  | @ -321,62 +298,62 @@ | |||
|       <PrivacyPolicy {state} /> | ||||
|     </Page> | ||||
| 
 | ||||
| 
 | ||||
|     <div class="subtle self-end"> | ||||
|       {Constants.vNumber} | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
| 
 | ||||
| 
 | ||||
| <style> | ||||
|     :global(.sidebar-unit) { | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|         row-gap: 0.25rem; | ||||
|         background: var(--background-color); | ||||
|         padding: 0.5rem; | ||||
|         border-radius: 0.5rem; | ||||
|     } | ||||
|   :global(.sidebar-unit) { | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     row-gap: 0.25rem; | ||||
|     background: var(--background-color); | ||||
|     padding: 0.5rem; | ||||
|     border-radius: 0.5rem; | ||||
|   } | ||||
| 
 | ||||
|     :global(.sidebar-unit > h3) { | ||||
|         margin-top: 0; | ||||
|         margin-bottom: 0.5rem; | ||||
|         padding: 0.25rem; | ||||
|     } | ||||
|   :global(.sidebar-unit > h3) { | ||||
|     margin-top: 0; | ||||
|     margin-bottom: 0.5rem; | ||||
|     padding: 0.25rem; | ||||
|   } | ||||
| 
 | ||||
|     :global(.sidebar-button svg, .sidebar-button img) { | ||||
|         width: 1.5rem; | ||||
|         height: 1.5rem; | ||||
|         margin-right: 0.5rem; | ||||
|         flex-shrink: 0; | ||||
|     } | ||||
|   :global(.sidebar-button svg, .sidebar-button img) { | ||||
|     width: 1.5rem; | ||||
|     height: 1.5rem; | ||||
|     margin-right: 0.5rem; | ||||
|     flex-shrink: 0; | ||||
|   } | ||||
| 
 | ||||
|     :global(.sidebar-button .weblate-link > svg) { | ||||
|         width: 0.75rem; | ||||
|         height: 0.75rem; | ||||
|         flex-shrink: 0; | ||||
|     } | ||||
|   :global(.sidebar-button .weblate-link > svg) { | ||||
|     width: 0.75rem; | ||||
|     height: 0.75rem; | ||||
|     flex-shrink: 0; | ||||
|   } | ||||
| 
 | ||||
|   :global(.sidebar-button, .sidebar-unit > a) { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     border-radius: 0.25rem !important; | ||||
|     padding: 0.4rem 0.75rem !important; | ||||
|     text-decoration: none !important; | ||||
|     width: 100%; | ||||
|     text-align: start; | ||||
|   } | ||||
| 
 | ||||
|     :global(.sidebar-button, .sidebar-unit > a) { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         border-radius: 0.25rem !important; | ||||
|         padding: 0.4rem 0.75rem !important; | ||||
|         text-decoration: none !important; | ||||
|         width: 100%; | ||||
|         text-align: start; | ||||
|     } | ||||
| 
 | ||||
|     :global(.sidebar-button > svg , .sidebar-button > img, .sidebar-unit a > img, .sidebar-unit > a svg) { | ||||
|         margin-right: 0.5rem; | ||||
|         flex-shrink: 0; | ||||
|     } | ||||
| 
 | ||||
|     :global(.sidebar-button:hover, .sidebar-unit > a:hover) { | ||||
|         background: var(--low-interaction-background) !important; | ||||
|     } | ||||
| 
 | ||||
|   :global( | ||||
|       .sidebar-button > svg, | ||||
|       .sidebar-button > img, | ||||
|       .sidebar-unit a > img, | ||||
|       .sidebar-unit > a svg | ||||
|     ) { | ||||
|     margin-right: 0.5rem; | ||||
|     flex-shrink: 0; | ||||
|   } | ||||
| 
 | ||||
|   :global(.sidebar-button:hover, .sidebar-unit > a:hover) { | ||||
|     background: var(--low-interaction-background) !important; | ||||
|   } | ||||
| </style> | ||||
|  |  | |||
|  | @ -74,9 +74,8 @@ | |||
|   </div> | ||||
|   <slot name="close-button"> | ||||
|     <div class="mt-4"> | ||||
|     <CloseButton  on:click={() => state.selectedElement.setData(undefined)}/> | ||||
|       <CloseButton on:click={() => state.selectedElement.setData(undefined)} /> | ||||
|     </div> | ||||
| 
 | ||||
|   </slot> | ||||
| </div> | ||||
| 
 | ||||
|  |  | |||
|  | @ -118,8 +118,7 @@ | |||
|   ) | ||||
| </script> | ||||
| 
 | ||||
| <div class="flex flex-col link-underline"> | ||||
| 
 | ||||
| <div class="link-underline flex flex-col"> | ||||
|   <a href="geo:{$location.lat},{$location.lon}">Open the current location in other applications</a> | ||||
| 
 | ||||
|   <div class="flex flex-col"> | ||||
|  |  | |||
|  | @ -63,7 +63,10 @@ | |||
|     <Tr t={layout.descriptionTail} /> | ||||
| 
 | ||||
|     <!-- Buttons: open map, go to location, search --> | ||||
|     <NextButton clss="primary w-full" on:click={() => state.guistate.pageStates.about_theme.setData(false)}> | ||||
|     <NextButton | ||||
|       clss="primary w-full" | ||||
|       on:click={() => state.guistate.pageStates.about_theme.setData(false)} | ||||
|     > | ||||
|       <div class="flex w-full flex-col items-center"> | ||||
|         <div class="flex w-full justify-center text-2xl"> | ||||
|           <Tr t={Translations.t.general.openTheMap} /> | ||||
|  | @ -136,10 +139,9 @@ | |||
|     {/if} | ||||
|   </div> | ||||
| 
 | ||||
|   <div class="link-underline flex justify-end text-sm mt-8"> | ||||
|   <div class="link-underline mt-8 flex justify-end text-sm"> | ||||
|     <a href="https://mapcomplete.org" target="_blank"> | ||||
|       <Tr t={Translations.t.general.poweredByMapComplete} /> | ||||
|     </a> | ||||
|   </div> | ||||
| 
 | ||||
| </div> | ||||
|  |  | |||
|  | @ -47,7 +47,6 @@ | |||
| </script> | ||||
| 
 | ||||
| <LoginToggle {state} silentFail> | ||||
| 
 | ||||
|   {#if !$sourceUrl || !$enableLogin} | ||||
|     <!-- empty block --> | ||||
|   {:else if $externalData === undefined} | ||||
|  | @ -59,15 +58,15 @@ | |||
|   {:else if $propertyKeysExternal.length === 0 && $knownImages.size + $unknownImages.length === 0} | ||||
|     <Tr cls="subtle" t={t.noDataLoaded} /> | ||||
|   {:else if !$hasDifferencesAtStart} | ||||
|   <span class="subtle text-sm"> | ||||
|     <Tr t={t.allIncluded.Subs({ source: $sourceUrl })} /> | ||||
|   </span> | ||||
|     <span class="subtle text-sm"> | ||||
|       <Tr t={t.allIncluded.Subs({ source: $sourceUrl })} /> | ||||
|     </span> | ||||
|   {:else if $comparisonState !== undefined} | ||||
|     <AccordionSingle expanded={!collapsed}> | ||||
|     <span slot="header" class="flex"> | ||||
|       <GlobeAlt class="h-6 w-6" /> | ||||
|       <Tr t={Translations.t.external.title} /> | ||||
|     </span> | ||||
|       <span slot="header" class="flex"> | ||||
|         <GlobeAlt class="h-6 w-6" /> | ||||
|         <Tr t={Translations.t.external.title} /> | ||||
|       </span> | ||||
|       <ComparisonTable | ||||
|         externalProperties={$externalData["success"]} | ||||
|         {state} | ||||
|  |  | |||
|  | @ -26,26 +26,28 @@ | |||
|   <div class="relative w-fit"> | ||||
|     <img | ||||
|       bind:this={imgEl} | ||||
|       on:load={() => loaded = true} | ||||
|       on:load={() => (loaded = true)} | ||||
|       class={imgClass ?? ""} | ||||
|       class:cursor-zoom-in={previewedImage !== undefined} | ||||
|       on:click={() => { | ||||
|       previewedImage?.setData(image) | ||||
|     }} | ||||
|         previewedImage?.setData(image) | ||||
|       }} | ||||
|       on:error={() => { | ||||
|       if (fallbackImage) { | ||||
|         imgEl.src = fallbackImage | ||||
|       } | ||||
|     }} | ||||
|         if (fallbackImage) { | ||||
|           imgEl.src = fallbackImage | ||||
|         } | ||||
|       }} | ||||
|       src={image.url} | ||||
|     /> | ||||
| 
 | ||||
|     {#if canZoom && loaded} | ||||
|       <div class="absolute right-0 top-0 bg-black-transparent rounded-bl-full" on:click={() => previewedImage.set(image)}> | ||||
|       <MagnifyingGlassPlusIcon class="w-8 h-8 pl-3 pb-3 cursor-zoom-in" color="white" /> | ||||
|       <div | ||||
|         class="bg-black-transparent absolute right-0 top-0 rounded-bl-full" | ||||
|         on:click={() => previewedImage.set(image)} | ||||
|       > | ||||
|         <MagnifyingGlassPlusIcon class="h-8 w-8 cursor-zoom-in pl-3 pb-3" color="white" /> | ||||
|       </div> | ||||
|     {/if} | ||||
| 
 | ||||
|   </div> | ||||
|   <div class="absolute bottom-0 left-0"> | ||||
|     <ImageAttribution {image} {attributionFormat} /> | ||||
|  |  | |||
|  | @ -20,7 +20,9 @@ | |||
| </script> | ||||
| 
 | ||||
| {#if $license !== undefined} | ||||
|   <div class="no-images flex items-center rounded-lg bg-black-transparent p-0.5 px-3 text-sm text-white"> | ||||
|   <div | ||||
|     class="no-images bg-black-transparent flex items-center rounded-lg p-0.5 px-3 text-sm text-white" | ||||
|   > | ||||
|     {#if icon !== undefined} | ||||
|       <div class="mr-2 h-6 w-6"> | ||||
|         <ToSvelte construct={icon} /> | ||||
|  | @ -28,7 +30,7 @@ | |||
|     {/if} | ||||
| 
 | ||||
|     <div class="flex gap-x-2" class:flex-col={attributionFormat !== "minimal"}> | ||||
|       {#if attributionFormat !== "minimal" } | ||||
|       {#if attributionFormat !== "minimal"} | ||||
|         {#if $license.title} | ||||
|           {#if $license.informationLocation} | ||||
|             <a href={$license.informationLocation.href} target="_blank" rel="noopener nofollower"> | ||||
|  | @ -42,7 +44,7 @@ | |||
| 
 | ||||
|       {#if $license.artist} | ||||
|         {#if attributionFormat === "large"} | ||||
|           <Tr t={Translations.t.general.attribution.madeBy.Subs({author: $license.artist})} /> | ||||
|           <Tr t={Translations.t.general.attribution.madeBy.Subs({ author: $license.artist })} /> | ||||
|         {:else} | ||||
|           <div class="font-bold"> | ||||
|             {@html $license.artist} | ||||
|  | @ -58,7 +60,7 @@ | |||
| 
 | ||||
|       {#if attributionFormat !== "minimal"} | ||||
|         <div class="flex w-full justify-between gap-x-1"> | ||||
|           {#if ($license.license !== undefined || $license.licenseShortName !== undefined)} | ||||
|           {#if $license.license !== undefined || $license.licenseShortName !== undefined} | ||||
|             <div> | ||||
|               {$license?.license ?? $license?.licenseShortName} | ||||
|             </div> | ||||
|  | @ -72,7 +74,6 @@ | |||
|           {/if} | ||||
|         </div> | ||||
|       {/if} | ||||
| 
 | ||||
|     </div> | ||||
|   </div> | ||||
| {/if} | ||||
|  |  | |||
|  | @ -39,10 +39,8 @@ | |||
|   <div | ||||
|     class="pointer-events-none absolute bottom-0 left-0 flex w-full flex-wrap items-end justify-between" | ||||
|   > | ||||
|     <div | ||||
|       class="pointer-events-auto m-1 w-fit transition-colors duration-200" | ||||
|     > | ||||
|       <ImageAttribution {image} attributionFormat="large"/> | ||||
|     <div class="pointer-events-auto m-1 w-fit transition-colors duration-200"> | ||||
|       <ImageAttribution {image} attributionFormat="large" /> | ||||
|     </div> | ||||
| 
 | ||||
|     <button | ||||
|  | @ -50,7 +48,7 @@ | |||
|       on:click={() => download()} | ||||
|     > | ||||
|       <DownloadIcon class="h-6 w-6 px-2 opacity-100" /> | ||||
|       <Tr t={Translations.t.general.download.downloadImage}/> | ||||
|       <Tr t={Translations.t.general.download.downloadImage} /> | ||||
|     </button> | ||||
|   </div> | ||||
| </div> | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ | |||
|     key: undefined, | ||||
|     provider: AllImageProviders.byName(image.provider), | ||||
|     date: new Date(image.date), | ||||
|     id: Object.values(image.osmTags)[0] | ||||
|     id: Object.values(image.osmTags)[0], | ||||
|   } | ||||
| 
 | ||||
|   async function applyLink(isLinked: boolean) { | ||||
|  | @ -44,7 +44,7 @@ | |||
|     if (isLinked) { | ||||
|       const action = new LinkImageAction(currentTags.id, key, url, tags, { | ||||
|         theme: tags.data._orig_theme ?? state.layout.id, | ||||
|         changeType: "link-image" | ||||
|         changeType: "link-image", | ||||
|       }) | ||||
|       await state.changes.applyAction(action) | ||||
|     } else { | ||||
|  | @ -53,7 +53,7 @@ | |||
|         if (v === url) { | ||||
|           const action = new ChangeTagAction(currentTags.id, new Tag(k, ""), currentTags, { | ||||
|             theme: tags.data._orig_theme ?? state.layout.id, | ||||
|             changeType: "remove-image" | ||||
|             changeType: "remove-image", | ||||
|           }) | ||||
|           state.changes.applyAction(action) | ||||
|         } | ||||
|  | @ -62,11 +62,13 @@ | |||
|   } | ||||
| 
 | ||||
|   isLinked.addCallback((isLinked) => applyLink(isLinked)) | ||||
| 
 | ||||
| </script> | ||||
| 
 | ||||
| <div class="flex w-fit shrink-0 flex-col rounded-lg overflow-hidden" class:border-interactive={$isLinked} | ||||
|      style="border-width: 2px"> | ||||
| <div | ||||
|   class="flex w-fit shrink-0 flex-col overflow-hidden rounded-lg" | ||||
|   class:border-interactive={$isLinked} | ||||
|   style="border-width: 2px" | ||||
| > | ||||
|   <AttributedImage | ||||
|     image={providedImage} | ||||
|     imgClass="max-h-64 w-auto" | ||||
|  |  | |||
|  | @ -13,12 +13,10 @@ export default class UrlValidator extends Validator { | |||
|         "tripadvisor.co.uk", | ||||
|         "tripadvisor.com.au", | ||||
|         "katestravelexperience.eu", | ||||
|         "hoteldetails.eu" | ||||
|         "hoteldetails.eu", | ||||
|     ]) | ||||
| 
 | ||||
|     private static readonly discouragedWebsites = new Set<string>([ | ||||
|         "facebook.com" | ||||
|     ]) | ||||
|     private static readonly discouragedWebsites = new Set<string>(["facebook.com"]) | ||||
| 
 | ||||
|     constructor(name?: string, explanation?: string, forceHttps?: boolean) { | ||||
|         super( | ||||
|  | @ -93,14 +91,10 @@ export default class UrlValidator extends Validator { | |||
|      * v.getFeedback("https://booking.com/some-hotel.html").textFor("en") // => Translations.t.validation.url.spamSite.Subs({host: "booking.com"}).textFor("en")
 | ||||
|      */ | ||||
|     getFeedback(s: string, getCountry?: () => string): Translation | undefined { | ||||
|         if ( | ||||
|             !s.startsWith("http://") && | ||||
|             !s.startsWith("https://") && | ||||
|             !s.startsWith("http:") | ||||
|         ) { | ||||
|         if (!s.startsWith("http://") && !s.startsWith("https://") && !s.startsWith("http:")) { | ||||
|             s = "https://" + s | ||||
|         } | ||||
|         try{ | ||||
|         try { | ||||
|             const url = new URL(s) | ||||
|             let host = url.host.toLowerCase() | ||||
|             if (host.startsWith("www.")) { | ||||
|  | @ -112,9 +106,7 @@ export default class UrlValidator extends Validator { | |||
|             if (UrlValidator.discouragedWebsites.has(host)) { | ||||
|                 return Translations.t.validation.url.aggregator.Subs({ host }) | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|         }catch (e) { | ||||
|         } catch (e) { | ||||
|             // pass
 | ||||
|         } | ||||
|         const upstream = super.getFeedback(s, getCountry) | ||||
|  | @ -122,7 +114,6 @@ export default class UrlValidator extends Validator { | |||
|             return upstream | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         return undefined | ||||
|     } | ||||
| 
 | ||||
|  | @ -131,7 +122,6 @@ export default class UrlValidator extends Validator { | |||
|      * v.isValid("https://booking.com/some-hotel.html") // => false
 | ||||
|      */ | ||||
|     isValid(str: string): boolean { | ||||
| 
 | ||||
|         try { | ||||
|             if ( | ||||
|                 !str.startsWith("http://") && | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ | |||
|     photo: ["photo", "historicphoto"], | ||||
|     map: ["map", "historicmap"], | ||||
|     other: ["other", "elevation"], | ||||
|     osmbasedmap: ["osmbasedmap"] | ||||
|     osmbasedmap: ["osmbasedmap"], | ||||
|   } | ||||
| 
 | ||||
|   function availableForCategory(type: CategoryType): Store<RasterLayerPolygon[]> { | ||||
|  | @ -51,20 +51,18 @@ | |||
|   } | ||||
| 
 | ||||
|   export let onlyLink: boolean | ||||
| 
 | ||||
| </script> | ||||
| 
 | ||||
| <Page {onlyLink} shown={shown} fullscreen={true}> | ||||
|   <div slot="header" class="flex" > | ||||
| <Page {onlyLink} {shown} fullscreen={true}> | ||||
|   <div slot="header" class="flex"> | ||||
|     <Square3Stack3dIcon class="h-6 w-6" /> | ||||
| 
 | ||||
|   <Tr t={Translations.t.general.backgroundMap} /> | ||||
|     <Tr t={Translations.t.general.backgroundMap} /> | ||||
|   </div> | ||||
|   {#if $_availableLayers?.length < 1} | ||||
|     <Loading /> | ||||
|   {:else} | ||||
| 
 | ||||
|     <div class="flex gap-x-2 flex-col sm:flex-row gap-y-2" style="height: calc( 100% - 5rem)"> | ||||
|     <div class="flex flex-col gap-x-2 gap-y-2 sm:flex-row" style="height: calc( 100% - 5rem)"> | ||||
|       <RasterLayerPicker | ||||
|         availableLayers={$photoLayers} | ||||
|         favourite={getPref("photo")} | ||||
|  |  | |||
|  | @ -55,7 +55,7 @@ | |||
| 
 | ||||
|     for (const preset of layer.presets) { | ||||
|       const tags = TagUtils.KVtoProperties(preset.tags ?? []) | ||||
|       if(preset.preciseInput.snapToLayers){ | ||||
|       if (preset.preciseInput.snapToLayers) { | ||||
|         tags["_referencing_ways"] = '["way/-1"]' | ||||
|       } | ||||
| 
 | ||||
|  |  | |||
|  | @ -386,7 +386,7 @@ | |||
|           /> | ||||
|         {:else if config.mappings !== undefined && !config.multiAnswer} | ||||
|           <!-- Simple radiobuttons as mapping --> | ||||
|           <div class="flex flex-col no-bold"> | ||||
|           <div class="no-bold flex flex-col"> | ||||
|             {#each config.mappings as mapping, i (mapping.then)} | ||||
|               <!-- Even though we have a list of 'mappings' already, we still iterate over the list as to keep the original indices--> | ||||
|               <TagRenderingMappingInput | ||||
|  | @ -401,7 +401,7 @@ | |||
|               > | ||||
|                 <input | ||||
|                   type="radio" | ||||
|                   class="self-center mr-1" | ||||
|                   class="mr-1 self-center" | ||||
|                   bind:group={selectedMapping} | ||||
|                   name={"mappings-radio-" + config.id} | ||||
|                   value={i} | ||||
|  | @ -413,7 +413,7 @@ | |||
|               <label class="flex gap-x-1"> | ||||
|                 <input | ||||
|                   type="radio" | ||||
|                   class="self-center mr-1" | ||||
|                   class="mr-1 self-center" | ||||
|                   bind:group={selectedMapping} | ||||
|                   name={"mappings-radio-" + config.id} | ||||
|                   value={config.mappings?.length} | ||||
|  | @ -436,7 +436,7 @@ | |||
|           </div> | ||||
|         {:else if config.mappings !== undefined && config.multiAnswer} | ||||
|           <!-- Multiple answers can be chosen: checkboxes --> | ||||
|           <div class="flex flex-col no-bold"> | ||||
|           <div class="no-bold flex flex-col"> | ||||
|             {#each config.mappings as mapping, i (mapping.then)} | ||||
|               <TagRenderingMappingInput | ||||
|                 {mapping} | ||||
|  | @ -450,7 +450,7 @@ | |||
|               > | ||||
|                 <input | ||||
|                   type="checkbox" | ||||
|                   class="self-center mr-1" | ||||
|                   class="mr-1 self-center" | ||||
|                   name={"mappings-checkbox-" + config.id + "-" + i} | ||||
|                   bind:checked={checkedMappings[i]} | ||||
|                   on:keypress={(e) => onInputKeypress(e)} | ||||
|  | @ -461,7 +461,7 @@ | |||
|               <label class="flex gap-x-1"> | ||||
|                 <input | ||||
|                   type="checkbox" | ||||
|                   class="self-center mr-1" | ||||
|                   class="mr-1 self-center" | ||||
|                   name={"mappings-checkbox-" + config.id + "-" + config.mappings?.length} | ||||
|                   bind:checked={checkedMappings[config.mappings.length]} | ||||
|                   on:keypress={(e) => onInputKeypress(e)} | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -28,8 +28,8 @@ | |||
|   } | ||||
| 
 | ||||
|   let configJson: Store<QuestionableTagRenderingConfigJson[]> = value.map((x) => { | ||||
|     if(x === undefined){ | ||||
|       console.log("No config found for ",path) | ||||
|     if (x === undefined) { | ||||
|       console.log("No config found for ", path) | ||||
|       return [] | ||||
|     } | ||||
|     if (typeof x === "string") { | ||||
|  |  | |||
|  | @ -13,9 +13,7 @@ | |||
|   import type { MapProperties } from "../Models/MapProperties" | ||||
|   import Geosearch from "./BigComponents/Geosearch.svelte" | ||||
|   import Translations from "./i18n/Translations" | ||||
|   import { | ||||
|     MenuIcon, | ||||
|   } from "@rgossiaux/svelte-heroicons/solid" | ||||
|   import { MenuIcon } from "@rgossiaux/svelte-heroicons/solid" | ||||
|   import Tr from "./Base/Tr.svelte" | ||||
|   import FloatOver from "./Base/FloatOver.svelte" | ||||
|   import Constants from "../Models/Constants" | ||||
|  | @ -73,7 +71,6 @@ | |||
|     }) | ||||
|   }) | ||||
| 
 | ||||
| 
 | ||||
|   let selectedLayer: Store<LayerConfig> = state.selectedElement.mapD((element) => { | ||||
|     const id = element.properties.id | ||||
|     if (id.startsWith("current_view")) { | ||||
|  | @ -100,11 +97,11 @@ | |||
|   state.mapProperties.installCustomKeyboardHandler(viewport) | ||||
|   let canZoomIn = mapproperties.maxzoom.map( | ||||
|     (mz) => mapproperties.zoom.data < mz, | ||||
|     [mapproperties.zoom], | ||||
|     [mapproperties.zoom] | ||||
|   ) | ||||
|   let canZoomOut = mapproperties.minzoom.map( | ||||
|     (mz) => mapproperties.zoom.data > mz, | ||||
|     [mapproperties.zoom], | ||||
|     [mapproperties.zoom] | ||||
|   ) | ||||
| 
 | ||||
|   function updateViewport() { | ||||
|  | @ -140,7 +137,7 @@ | |||
|   onDestroy( | ||||
|     rasterLayer.addCallbackAndRunD((l) => { | ||||
|       rasterLayerName = l.properties.name | ||||
|     }), | ||||
|     }) | ||||
|   ) | ||||
|   let previewedImage = state.previewedImage | ||||
|   let addNewFeatureMode = state.userRelatedState.addNewFeatureMode | ||||
|  | @ -148,7 +145,6 @@ | |||
|   let gpsButtonAriaLabel = state.geolocation.geolocationState.gpsStateExplanation | ||||
|   let debug = state.featureSwitches.featureSwitchIsDebugging | ||||
| 
 | ||||
| 
 | ||||
|   debug.addCallbackAndRun((dbg) => { | ||||
|     if (dbg) { | ||||
|       document.body.classList.add("debug") | ||||
|  | @ -193,14 +189,17 @@ | |||
|     <!-- Top components --> | ||||
| 
 | ||||
|     <div | ||||
|       class="flex bg-black-light-transparent pointer-events-auto items-center justify-between px-4 py-1 flex-wrap-reverse"> | ||||
|       class="bg-black-light-transparent pointer-events-auto flex flex-wrap-reverse items-center justify-between px-4 py-1" | ||||
|     > | ||||
|       <!-- Top bar with tools --> | ||||
|       <div class="flex items-center"> | ||||
| 
 | ||||
|         <MapControlButton | ||||
|           cls="m-0.5 p-0.5 sm:p-1" | ||||
|           arialabel={Translations.t.general.labels.menu} | ||||
|           on:click={() => {console.log("Opening...."); state.guistate.pageStates.menu.setData(true)}} | ||||
|           on:click={() => { | ||||
|             console.log("Opening....") | ||||
|             state.guistate.pageStates.menu.setData(true) | ||||
|           }} | ||||
|           on:keydown={forwardEventToMap} | ||||
|         > | ||||
|           <MenuIcon class="h-6 w-6 cursor-pointer" /> | ||||
|  | @ -210,9 +209,7 @@ | |||
|           on:click={() => state.guistate.pageStates.about_theme.set(true)} | ||||
|           on:keydown={forwardEventToMap} | ||||
|         > | ||||
|           <div | ||||
|             class="m-0.5 mx-1 flex cursor-pointer items-center max-[480px]:w-full sm:mx-1 mr-2" | ||||
|           > | ||||
|           <div class="m-0.5 mx-1 mr-2 flex cursor-pointer items-center max-[480px]:w-full sm:mx-1"> | ||||
|             <Marker icons={layout.icon} size="h-6 w-6 shrink-0 mr-0.5 sm:mr-1 md:mr-2" /> | ||||
|             <b class="mr-1"> | ||||
|               <Tr t={layout.title} /> | ||||
|  | @ -228,20 +225,18 @@ | |||
|       {/if} | ||||
| 
 | ||||
|       <If condition={state.featureSwitches.featureSwitchSearch}> | ||||
|         <div class="w-full sm:w-64 my-2 sm:mt-0"> | ||||
| 
 | ||||
|         <div class="my-2 w-full sm:mt-0 sm:w-64"> | ||||
|           <Geosearch | ||||
|             bounds={state.mapProperties.bounds} | ||||
|             on:searchCompleted={() => { | ||||
|             state.map?.data?.getCanvas()?.focus() | ||||
|           }} | ||||
|               state.map?.data?.getCanvas()?.focus() | ||||
|             }} | ||||
|             perLayer={state.perLayer} | ||||
|             selectedElement={state.selectedElement} | ||||
|             geolocationState={state.geolocation.geolocationState} | ||||
|           /> | ||||
|         </div> | ||||
|       </If> | ||||
| 
 | ||||
|     </div> | ||||
| 
 | ||||
|     <div class="pointer-events-auto float-right mt-1 flex flex-col px-1 max-[480px]:w-full sm:m-2"> | ||||
|  | @ -252,13 +247,9 @@ | |||
|           </div> | ||||
|         {/if} | ||||
|       </If> | ||||
| 
 | ||||
|     </div> | ||||
|     <div class="float-left m-1 flex flex-col sm:mt-2"> | ||||
|       <If condition={state.featureSwitches.featureSwitchWelcomeMessage}> | ||||
| 
 | ||||
| 
 | ||||
|       </If> | ||||
|       <If condition={state.featureSwitches.featureSwitchWelcomeMessage} /> | ||||
|       {#if currentViewLayer?.tagRenderings && currentViewLayer.defaultIcon()} | ||||
|         <MapControlButton | ||||
|           on:click={() => { | ||||
|  | @ -329,15 +320,14 @@ | |||
|             </MapControlButton> | ||||
|           </If> | ||||
|           <If condition={state.featureSwitches.featureSwitchBackgroundSelection}> | ||||
|             <OpenBackgroundSelectorButton | ||||
|               hideTooltip={true} | ||||
|               {state} | ||||
|             /> | ||||
|             <OpenBackgroundSelectorButton hideTooltip={true} {state} /> | ||||
|           </If> | ||||
|           <button | ||||
|             class="unstyled bg-black-transparent pointer-events-auto ml-1 h-fit max-h-12 cursor-pointer overflow-hidden rounded-2xl px-1 text-white opacity-50 hover:opacity-100" | ||||
|             style="background: #00000088; padding: 0.25rem; border-radius: 2rem;" | ||||
|             on:click={() => {state.guistate.pageStates.copyright.set(true)}} | ||||
|             on:click={() => { | ||||
|               state.guistate.pageStates.copyright.set(true) | ||||
|             }} | ||||
|           > | ||||
|             © <span class="hidden sm:inline sm:pr-2"> | ||||
|               OpenStreetMap | ||||
|  | @ -450,7 +440,11 @@ | |||
|           state.selectedElement.setData(undefined) | ||||
|         }} | ||||
|       > | ||||
|         <SelectedElementView {state} layer={$selectedLayer} selectedElement={$state_selectedElement} /> | ||||
|         <SelectedElementView | ||||
|           {state} | ||||
|           layer={$selectedLayer} | ||||
|           selectedElement={$state_selectedElement} | ||||
|         /> | ||||
|       </FloatOver> | ||||
|     {/if} | ||||
|   {/if} | ||||
|  | @ -461,6 +455,4 @@ | |||
|       <ImageOperations image={$previewedImage} /> | ||||
|     </FloatOver> | ||||
|   </If> | ||||
| 
 | ||||
| 
 | ||||
| </main> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue