forked from MapComplete/MapComplete
		
	UX: usersetting visual cleanup, add 'clear caches'-option, version bump
This commit is contained in:
		
							parent
							
								
									87a3efb0c5
								
							
						
					
					
						commit
						9b7cdb3c17
					
				
					 13 changed files with 108 additions and 28 deletions
				
			
		|  | @ -617,12 +617,14 @@ | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "id": "mangrove-keys", |       "id": "mangrove-keys", | ||||||
|       "classes": "flex flex-col", |       "classes": "link-no-underline low-interaction p-2", | ||||||
|       "render": { |       "render": { | ||||||
|         "special": { |         "special": { | ||||||
|           "type": "link", |           "type": "link", | ||||||
|           "href": "data:application/json,{mangroveidentity}", |           "href": "data:application/json,{mangroveidentity}", | ||||||
|           "download": "mangrove_private_key_{_name}", |           "download": "mangrove_private_key_{_name}", | ||||||
|  |           "class": "button", | ||||||
|  | 
 | ||||||
|           "text": { |           "text": { | ||||||
|             "en": "Download the private key for your Mangrove Account", |             "en": "Download the private key for your Mangrove Account", | ||||||
|             "de": "Laden Sie den privaten Schlüssel für Ihr Mangrove-Konto herunter", |             "de": "Laden Sie den privaten Schlüssel für Ihr Mangrove-Konto herunter", | ||||||
|  | @ -645,6 +647,7 @@ | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "id": "mangrove-key-import", |       "id": "mangrove-key-import", | ||||||
|  |       "classes": "low-interaction p-2", | ||||||
|       "render": { |       "render": { | ||||||
|         "special": { |         "special": { | ||||||
|           "type": "import_mangrove_key", |           "type": "import_mangrove_key", | ||||||
|  | @ -901,6 +904,27 @@ | ||||||
|         } |         } | ||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|  |     { | ||||||
|  |       "id": "debug-title", | ||||||
|  |       "render": { | ||||||
|  |         "en": "<h3>Debugging options</h3>" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "id": "clear_cache", | ||||||
|  |       "classes": "low-interaction p-2", | ||||||
|  |       "render": { | ||||||
|  |         "special": { | ||||||
|  |           "type": "clear_caches", | ||||||
|  |           "text": { | ||||||
|  |             "en": "Clear caches" | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "after": { | ||||||
|  |           "en": "Clearing the caches will delete locally downloaded data and code. You will remain logged in and your settings will be preserved. No data should be lost" | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     { |     { | ||||||
|       "id": "pending_changes", |       "id": "pending_changes", | ||||||
|       "render": { |       "render": { | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| { | { | ||||||
|   "name": "mapcomplete", |   "name": "mapcomplete", | ||||||
|   "version": "0.44.14", |   "version": "0.45.0", | ||||||
|   "repository": "https://github.com/pietervdvn/MapComplete", |   "repository": "https://github.com/pietervdvn/MapComplete", | ||||||
|   "description": "A small website to edit OSM easily", |   "description": "A small website to edit OSM easily", | ||||||
|   "bugs": "https://github.com/pietervdvn/MapComplete/issues", |   "bugs": "https://github.com/pietervdvn/MapComplete/issues", | ||||||
|  |  | ||||||
|  | @ -993,6 +993,10 @@ video { | ||||||
|   margin-right: 4rem; |   margin-right: 4rem; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .mb-4 { | ||||||
|  |   margin-bottom: 1rem; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .mt-4 { | .mt-4 { | ||||||
|   margin-top: 1rem; |   margin-top: 1rem; | ||||||
| } | } | ||||||
|  | @ -1025,10 +1029,6 @@ video { | ||||||
|   margin-right: 0.25rem; |   margin-right: 0.25rem; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .mb-4 { |  | ||||||
|   margin-bottom: 1rem; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .ml-1 { | .ml-1 { | ||||||
|   margin-left: 0.25rem; |   margin-left: 0.25rem; | ||||||
| } | } | ||||||
|  | @ -1221,14 +1221,14 @@ video { | ||||||
|   height: 6rem; |   height: 6rem; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .h-full { |  | ||||||
|   height: 100%; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .h-screen { | .h-screen { | ||||||
|   height: 100vh; |   height: 100vh; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .h-full { | ||||||
|  |   height: 100%; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .h-fit { | .h-fit { | ||||||
|   height: -webkit-fit-content; |   height: -webkit-fit-content; | ||||||
|   height: -moz-fit-content; |   height: -moz-fit-content; | ||||||
|  | @ -3353,6 +3353,11 @@ video { | ||||||
|   padding-right: 0.25rem; |   padding-right: 0.25rem; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .py-8 { | ||||||
|  |   padding-top: 2rem; | ||||||
|  |   padding-bottom: 2rem; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .px-3 { | .px-3 { | ||||||
|   padding-left: 0.75rem; |   padding-left: 0.75rem; | ||||||
|   padding-right: 0.75rem; |   padding-right: 0.75rem; | ||||||
|  | @ -4858,7 +4863,7 @@ a.link-underline { | ||||||
|   -webkit-text-decoration: underline; |   -webkit-text-decoration: underline; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .link-no-underline a { | .link-no-underline a, a.link-no-underline { | ||||||
|   text-decoration: none; |   text-decoration: none; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
|   import { ImmutableStore, Store } from "../../Logic/UIEventSource" |   import { ImmutableStore, Store } from "../../Logic/UIEventSource" | ||||||
|  |   import Icon from "../Map/Icon.svelte" | ||||||
| 
 | 
 | ||||||
|   export let text: Store<string> |   export let text: Store<string> | ||||||
|   export let href: Store<string> |   export let href: Store<string> | ||||||
|  | @ -8,6 +9,7 @@ | ||||||
|   export let ariaLabel: Store<string> = undefined |   export let ariaLabel: Store<string> = undefined | ||||||
| 
 | 
 | ||||||
|   export let newTab: Store<boolean> = new ImmutableStore(false) |   export let newTab: Store<boolean> = new ImmutableStore(false) | ||||||
|  |   export let icon: Store<string> = undefined | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <a | <a | ||||||
|  | @ -18,5 +20,8 @@ | ||||||
|   download={$download} |   download={$download} | ||||||
|   class={$classnames} |   class={$classnames} | ||||||
| > | > | ||||||
|  |   {#if $icon} | ||||||
|  |     <Icon clss="w-8 h-8" icon={$icon}/> | ||||||
|  |     {/if} | ||||||
|   {@html $text} |   {@html $text} | ||||||
| </a> | </a> | ||||||
|  |  | ||||||
|  | @ -9,7 +9,6 @@ | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <button | <button | ||||||
|   class="as-link" |  | ||||||
|   on:click={() => { |   on:click={() => { | ||||||
|     osmConnection.LogOut() |     osmConnection.LogOut() | ||||||
|   }} |   }} | ||||||
|  |  | ||||||
|  | @ -32,12 +32,19 @@ | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| {#if isSvelte} | {#if isSvelte} | ||||||
|   <svelte:component |   {#if svelteElem.getClass() || svelteElem.getStyle()} | ||||||
|     this={svelteElem?._svelteComponent} |     <svelte:component | ||||||
|     {...svelteElem._props} |       this={svelteElem?._svelteComponent} | ||||||
|     class={svelteElem.getClass()} |       {...svelteElem._props} | ||||||
|     style={svelteElem.getStyle()} |       class={svelteElem.getClass()} | ||||||
|   /> |       style={svelteElem.getStyle()} | ||||||
|  |     /> | ||||||
|  |   {:else} | ||||||
|  |     <svelte:component | ||||||
|  |       this={svelteElem?._svelteComponent} | ||||||
|  |       {...svelteElem._props} | ||||||
|  |     /> | ||||||
|  |   {/if} | ||||||
| {:else} | {:else} | ||||||
|   <span bind:this={elem} /> |   <span bind:this={elem} /> | ||||||
| {/if} | {/if} | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|   import Locale from "../i18n/Locale" |   import Locale from "../i18n/Locale" | ||||||
|   import LinkToWeblate from "./LinkToWeblate" |   import LinkToWeblate from "./LinkToWeblate" | ||||||
|   import Translate from "../../assets/svg/Translate.svelte" |   import Translate from "../../assets/svg/Translate.svelte" | ||||||
|  |   import { LanguageIcon } from "@babeard/svelte-heroicons/solid" | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Shows a small icon which will open up weblate; a contributor can translate the item for 'context' there |    * Shows a small icon which will open up weblate; a contributor can translate the item for 'context' there | ||||||
|  | @ -26,11 +27,11 @@ | ||||||
|   {:else if $linkToWeblate} |   {:else if $linkToWeblate} | ||||||
|     <a |     <a | ||||||
|       href={LinkToWeblate.hrefToWeblate($language, context)} |       href={LinkToWeblate.hrefToWeblate($language, context)} | ||||||
|       class="weblate-link hidden-on-mobile mx-1" |       class="weblate-link hidden-on-mobile" | ||||||
|       target="_blank" |       target="_blank" | ||||||
|       tabindex="-1" |       tabindex="-1" | ||||||
|     > |     > | ||||||
|       <Translate class="font-gray inline-block" /> |       <LanguageIcon class="font-gray"/> | ||||||
|     </a> |     </a> | ||||||
|   {/if} |   {/if} | ||||||
| {/if} | {/if} | ||||||
|  |  | ||||||
|  | @ -46,7 +46,7 @@ | ||||||
|       <LanguageIcon class="mr-1 h-4 w-4 shrink-0" aria-hidden="true" /> |       <LanguageIcon class="mr-1 h-4 w-4 shrink-0" aria-hidden="true" /> | ||||||
|     </label> |     </label> | ||||||
| 
 | 
 | ||||||
|     <Dropdown cls="max-w-full" value={assignTo} id="pick-language"> |     <Dropdown cls="max-w-full" value={assignTo}> | ||||||
|       {#if preferredFiltered} |       {#if preferredFiltered} | ||||||
|         {#each preferredFiltered as language} |         {#each preferredFiltered as language} | ||||||
|           <option value={language} class="font-bold"> |           <option value={language} class="font-bold"> | ||||||
|  |  | ||||||
							
								
								
									
										16
									
								
								src/UI/Popup/ClearCaches.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/UI/Popup/ClearCaches.svelte
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | <script lang="ts"> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   import { IdbLocalStorage } from "../../Logic/Web/IdbLocalStorage" | ||||||
|  |   import { Utils } from "../../Utils" | ||||||
|  | 
 | ||||||
|  |   function clearCaches(){ | ||||||
|  |     IdbLocalStorage.clearAll() | ||||||
|  |     Utils.download("./service-worker-clear") | ||||||
|  |   } | ||||||
|  |   export let msg : string | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <button on:click={() => clearCaches()} class="flex gap-x-2"> | ||||||
|  |   {msg} | ||||||
|  | </button> | ||||||
|  | @ -100,8 +100,8 @@ import { CombinedFetcher } from "../Logic/Web/NearbyImagesSearch" | ||||||
| import { And } from "../Logic/Tags/And" | import { And } from "../Logic/Tags/And" | ||||||
| import CloseNoteButton from "./Popup/Notes/CloseNoteButton.svelte" | import CloseNoteButton from "./Popup/Notes/CloseNoteButton.svelte" | ||||||
| import PendingChangesIndicator from "./BigComponents/PendingChangesIndicator.svelte" | import PendingChangesIndicator from "./BigComponents/PendingChangesIndicator.svelte" | ||||||
| import Loading from "./Base/Loading" |  | ||||||
| import QrCode from "./Popup/QrCode.svelte" | import QrCode from "./Popup/QrCode.svelte" | ||||||
|  | import ClearCaches from "./Popup/ClearCaches.svelte" | ||||||
| 
 | 
 | ||||||
| class NearbyImageVis implements SpecialVisualization { | class NearbyImageVis implements SpecialVisualization { | ||||||
|     // Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
 |     // Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
 | ||||||
|  | @ -1309,6 +1309,10 @@ export default class SpecialVisualizations { | ||||||
|                         name: "arialabel", |                         name: "arialabel", | ||||||
|                         doc: "If set, this text will be used as aria-label", |                         doc: "If set, this text will be used as aria-label", | ||||||
|                     }, |                     }, | ||||||
|  |                     { | ||||||
|  |                         name: "icon", | ||||||
|  |                         doc: "If set, show this icon next to the link. You might want to combine this with `class: button`" | ||||||
|  |                     } | ||||||
|                 ], |                 ], | ||||||
| 
 | 
 | ||||||
|                 constr( |                 constr( | ||||||
|  | @ -1316,7 +1320,7 @@ export default class SpecialVisualizations { | ||||||
|                     tagSource: UIEventSource<Record<string, string>>, |                     tagSource: UIEventSource<Record<string, string>>, | ||||||
|                     args: string[] |                     args: string[] | ||||||
|                 ): BaseUIElement { |                 ): BaseUIElement { | ||||||
|                     let [text, href, classnames, download, ariaLabel] = args |                     let [text, href, classnames, download, ariaLabel, icon] = args | ||||||
|                     if (download === "") { |                     if (download === "") { | ||||||
|                         download = undefined |                         download = undefined | ||||||
|                     } |                     } | ||||||
|  | @ -1684,7 +1688,6 @@ export default class SpecialVisualizations { | ||||||
|             { |             { | ||||||
|                 funcName: "qr_code", |                 funcName: "qr_code", | ||||||
|                 args: [], |                 args: [], | ||||||
| 
 |  | ||||||
|                 docs: "Generates a QR-code to share the selected object", |                 docs: "Generates a QR-code to share the selected object", | ||||||
|                 constr( |                 constr( | ||||||
|                     state: SpecialVisualizationState, |                     state: SpecialVisualizationState, | ||||||
|  | @ -1990,6 +1993,20 @@ export default class SpecialVisualizations { | ||||||
|                 constr(state: SpecialVisualizationState, tagSource: UIEventSource<Record<string, string>>, argument: string[], feature: Feature, layer: LayerConfig): BaseUIElement { |                 constr(state: SpecialVisualizationState, tagSource: UIEventSource<Record<string, string>>, argument: string[], feature: Feature, layer: LayerConfig): BaseUIElement { | ||||||
|                     return new SvelteUIElement(PendingChangesIndicator, {state, compact: false}) |                     return new SvelteUIElement(PendingChangesIndicator, {state, compact: false}) | ||||||
|                 } |                 } | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 funcName: "clear_caches", | ||||||
|  |                 docs: "A button which clears the locally downloaded data and the service worker. Login status etc will be kept", | ||||||
|  |                 args:[ | ||||||
|  |                     { | ||||||
|  |                         name: "text", | ||||||
|  |                         required: true, | ||||||
|  |                         doc: "The text to show on the button" | ||||||
|  |                     } | ||||||
|  |                 ], | ||||||
|  |                 constr(state: SpecialVisualizationState, tagSource: UIEventSource<Record<string, string>>, argument: string[], feature: Feature, layer: LayerConfig): SvelteUIElement { | ||||||
|  |                     return new SvelteUIElement<any, any, any>(ClearCaches, {msg: argument[0] ?? "Clear local caches"}) | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         ] |         ] | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -615,7 +615,7 @@ | ||||||
|           <Tr t={UserRelatedState.usersettingsConfig.title.GetRenderValue({})} /> |           <Tr t={UserRelatedState.usersettingsConfig.title.GetRenderValue({})} /> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <div class="links-as-button" slot="content1"> |         <div class="links-as-button py-8" slot="content1"> | ||||||
|           <!-- All shown components are set by 'usersettings.json', which happily uses some special visualisations created specifically for it --> |           <!-- All shown components are set by 'usersettings.json', which happily uses some special visualisations created specifically for it --> | ||||||
|           <LoginToggle {state}> |           <LoginToggle {state}> | ||||||
|             <div class="flex flex-col" slot="not-logged-in"> |             <div class="flex flex-col" slot="not-logged-in"> | ||||||
|  |  | ||||||
|  | @ -508,7 +508,7 @@ a.link-underline { | ||||||
|   -webkit-text-decoration: underline; |   -webkit-text-decoration: underline; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .link-no-underline a { | .link-no-underline a, a.link-no-underline { | ||||||
|   text-decoration: none; |   text-decoration: none; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -44,7 +44,7 @@ const cacheFirst = async (event, attemptUpdate: boolean = false) => { | ||||||
|                 return cacheResponse |                 return cacheResponse | ||||||
|             } |             } | ||||||
|             return fetchAndCache(event) |             return fetchAndCache(event) | ||||||
|         }) |         }), | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -57,10 +57,16 @@ self.addEventListener("fetch", async (e) => { | ||||||
|         if (requestUrl.pathname.endsWith("service-worker-version")) { |         if (requestUrl.pathname.endsWith("service-worker-version")) { | ||||||
|             console.log("Sending version number...") |             console.log("Sending version number...") | ||||||
|             await event.respondWith( |             await event.respondWith( | ||||||
|                 new Response(JSON.stringify({ "service-worker-version": version })) |                 new Response(JSON.stringify({ "service-worker-version": version })), | ||||||
|             ) |             ) | ||||||
|             return |             return | ||||||
|         } |         } | ||||||
|  |         if (requestUrl.pathname.endsWith("/service-worker-clear")) { | ||||||
|  |             const keys = await caches.keys() | ||||||
|  |             await Promise.all(keys.map(k => caches.delete(k))) | ||||||
|  |             console.log("Cleared caches") | ||||||
|  |             return | ||||||
|  |         } | ||||||
|         const shouldBeCached = |         const shouldBeCached = | ||||||
|             origin.host === requestUrl.host && |             origin.host === requestUrl.host && | ||||||
|             origin.hostname !== "127.0.0.1" && |             origin.hostname !== "127.0.0.1" && | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue