forked from MapComplete/MapComplete
		
	Add grid overview to index page
This commit is contained in:
		
							parent
							
								
									00fb194dc2
								
							
						
					
					
						commit
						01bf69a678
					
				
					 5 changed files with 100 additions and 98 deletions
				
			
		|  | @ -4,17 +4,19 @@ import Combine from "./Combine"; | |||
| import {FixedUiElement} from "./FixedUiElement"; | ||||
| 
 | ||||
| 
 | ||||
| export class SubtleButton extends UIElement{ | ||||
|     private readonly image: UIElement; | ||||
|     private readonly message: UIElement; | ||||
|     private readonly linkTo: { url: string, newTab?: boolean } = undefined; | ||||
| export class SubtleButton extends Combine { | ||||
| 
 | ||||
|     constructor(imageUrl: string | UIElement, message: string | UIElement, linkTo: { url: string, newTab?: boolean } = undefined) { | ||||
|         super(undefined); | ||||
|         this.linkTo = linkTo; | ||||
|         this.message = Translations.W(message); | ||||
|         if(this.message !== null){ | ||||
|             this.message.dumbMode = false; | ||||
|         super(SubtleButton.generateContent(imageUrl, message, linkTo)); | ||||
| 
 | ||||
|         this.SetClass("block flex p-3 my-2 bg-blue-100 rounded-lg hover:shadow-xl hover:bg-blue-200 link-no-underline") | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private static generateContent(imageUrl: string | UIElement, messageT: string | UIElement, linkTo: { url: string, newTab?: boolean } = undefined): (UIElement | string)[] { | ||||
|         const message = Translations.W(messageT); | ||||
|         if (message !== null) { | ||||
|             message.dumbMode = false; | ||||
|         } | ||||
|         let img; | ||||
|         if ((imageUrl ?? "") === "") { | ||||
|  | @ -25,35 +27,31 @@ export class SubtleButton extends UIElement{ | |||
|             img = imageUrl; | ||||
|         } | ||||
|         img.SetClass("block flex items-center justify-center h-11 w-11 flex-shrink0") | ||||
|         this.image = new Combine([img]) | ||||
|         const image = new Combine([img]) | ||||
|             .SetClass("flex-shrink-0"); | ||||
|          | ||||
|         | ||||
|     } | ||||
| 
 | ||||
|     InnerRender(): string { | ||||
| 
 | ||||
|         if(this.message !== null && this.message.IsEmpty()){ | ||||
|         if (message !== null && message.IsEmpty()) { | ||||
|             // Message == null: special case to force empty text
 | ||||
|             return ""; | ||||
|             return []; | ||||
|         } | ||||
| 
 | ||||
|         if(this.linkTo != undefined){ | ||||
|             return new Combine([ | ||||
|                 `<a class='block flex group p-3 my-2 bg-blue-100 rounded-lg hover:shadow-xl hover:bg-blue-200' href="${this.linkTo.url}" ${this.linkTo.newTab ? 'target="_blank"' : ""}>`, | ||||
|                 this.image, | ||||
|                 `<div class='ml-4'>`, | ||||
|                 this.message, | ||||
|         if (linkTo != undefined) { | ||||
|             return [ | ||||
|                 `<a class='flex group' href="${linkTo.url}" ${linkTo.newTab ? 'target="_blank"' : ""}>`, | ||||
|                 image, | ||||
|                 `<div class='ml-4 overflow-ellipsis'>`, | ||||
|                 message, | ||||
|                 `</div>`, | ||||
|                 `</a>` | ||||
|             ]).Render(); | ||||
|             ]; | ||||
|         } | ||||
| 
 | ||||
|         return new Combine([ | ||||
|             this.image, | ||||
|             this.message, | ||||
|         ]).SetClass("block flex p-3 my-2 bg-blue-100 rounded-lg hover:shadow-xl hover:bg-blue-200 link-no-underline") | ||||
|             .Render(); | ||||
|         return [ | ||||
|             image, | ||||
|             message, | ||||
|         ]; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,12 +25,78 @@ export default class MoreScreen extends UIElement { | |||
|         this.ListenTo(State.state.installedThemes); | ||||
|     } | ||||
| 
 | ||||
|     InnerRender(): string { | ||||
| 
 | ||||
|         const tr = Translations.t.general.morescreen; | ||||
| 
 | ||||
|         const els: UIElement[] = [] | ||||
| 
 | ||||
|         const themeButtons: UIElement[] = [] | ||||
| 
 | ||||
|         for (const layout of AllKnownLayouts.layoutsList) { | ||||
|             if (layout.id === personal.id) { | ||||
|                 if (State.state.osmConnection.userDetails.data.csCount < Constants.userJourney.personalLayoutUnlock) { | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|             themeButtons.push(this.createLinkButton(layout)); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         els.push(new VariableUiElement( | ||||
|             State.state.osmConnection.userDetails.map(userDetails => { | ||||
|                 if (userDetails.csCount < Constants.userJourney.themeGeneratorReadOnlyUnlock) { | ||||
|                     return new SubtleButton(null, tr.requestATheme, {url:"https://github.com/pietervdvn/MapComplete/issues", newTab: true}).Render(); | ||||
|                 } | ||||
|                 return new SubtleButton(Svg.pencil_ui(), tr.createYourOwnTheme, { | ||||
|                     url: "./customGenerator.html", | ||||
|                     newTab: false | ||||
|                 }).Render(); | ||||
|             }) | ||||
|         )); | ||||
| 
 | ||||
|         els.push(new Combine(themeButtons)) | ||||
| 
 | ||||
| 
 | ||||
|         const customThemesNames = State.state.installedThemes.data ?? []; | ||||
| 
 | ||||
|         if (customThemesNames.length > 0) { | ||||
|             els.push(Translations.t.general.customThemeIntro) | ||||
| 
 | ||||
|             for (const installed of State.state.installedThemes.data) { | ||||
|                 els.push(this.createLinkButton(installed.layout, installed.definition)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         let intro: UIElement = tr.intro; | ||||
|         const themeButtonsElement = new Combine(els) | ||||
| 
 | ||||
|         if (this._onMainScreen) { | ||||
|             intro = new Combine([ | ||||
|                 LanguagePicker.CreateLanguagePicker(Translations.t.index.title.SupportedLanguages()) | ||||
|                     .SetClass("absolute top-2 right-3"), | ||||
|                 new IndexText() | ||||
|             ]) | ||||
|             themeButtons.map(e => e?.SetClass("h-32 min-h-32 max-h-32 overflow-ellipsis overflow-hidden")) | ||||
|             themeButtonsElement.SetClass("md:grid md:grid-flow-row md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-g4 gap-4") | ||||
|         } | ||||
| 
 | ||||
|          | ||||
| 
 | ||||
|         this._component = new Combine([ | ||||
|             intro, | ||||
|             themeButtonsElement, | ||||
|             tr.streetcomplete.SetClass("block text-base mx-10 my-3 mb-10") | ||||
|         ]); | ||||
|         return this._component.Render(); | ||||
|     } | ||||
| 
 | ||||
|     private createLinkButton(layout: LayoutConfig, customThemeDefinition: string = undefined) { | ||||
|         if (layout === undefined) { | ||||
|             return undefined; | ||||
|         } | ||||
|         if(layout.id === undefined){ | ||||
|             console.error("ID is undefined for layout",layout); | ||||
|         if (layout.id === undefined) { | ||||
|             console.error("ID is undefined for layout", layout); | ||||
|             return undefined; | ||||
|         } | ||||
|         if (layout.hideFromOverview) { | ||||
|  | @ -49,10 +115,10 @@ export default class MoreScreen extends UIElement { | |||
|         // Path starts with a '/' and contains everything, e.g. '/dir/dir/page.html'
 | ||||
|         path = path.substr(0, path.lastIndexOf("/")); | ||||
|         // Path will now contain '/dir/dir', or empty string in case of nothing
 | ||||
|         if(path === ""){ | ||||
|         if (path === "") { | ||||
|             path = "." | ||||
|         } | ||||
|          | ||||
| 
 | ||||
|         const params = `z=${currentLocation.zoom ?? 1}&lat=${currentLocation.lat ?? 0}&lon=${currentLocation.lon ?? 0}` | ||||
|         let linkText = | ||||
|             `${path}/${layout.id.toLowerCase()}.html?${params}` | ||||
|  | @ -72,73 +138,10 @@ export default class MoreScreen extends UIElement { | |||
|                 `<dt class='text-lg leading-6 font-medium text-gray-900 group-hover:text-blue-800'>`, | ||||
|                 Translations.W(layout.title), | ||||
|                 `</dt>`, | ||||
|                 `<dd class='mt-1 text-base text-gray-500 group-hover:text-blue-900'>`, | ||||
|                 `<dd class='mt-1 text-base text-gray-500 group-hover:text-blue-900 overflow-ellipsis'>`, | ||||
|                 description ?? "", | ||||
|                 `</dd>`, | ||||
|             ]), {url: linkText, newTab: false}); | ||||
|     } | ||||
| 
 | ||||
|     InnerRender(): string { | ||||
| 
 | ||||
|         const tr = Translations.t.general.morescreen; | ||||
| 
 | ||||
|         const els: UIElement[] = [] | ||||
| 
 | ||||
|         const linkButton: UIElement[] = [] | ||||
| 
 | ||||
|         for (const layout of AllKnownLayouts.layoutsList) { | ||||
|             if (layout.id === personal.id) { | ||||
|                 if (State.state.osmConnection.userDetails.data.csCount < Constants.userJourney.personalLayoutUnlock) { | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|             linkButton.push(this.createLinkButton(layout)); | ||||
|         } | ||||
| 
 | ||||
|         | ||||
|         els.push(new VariableUiElement( | ||||
|             State.state.osmConnection.userDetails.map(userDetails => { | ||||
|                 if (userDetails.csCount < Constants.userJourney.themeGeneratorReadOnlyUnlock) { | ||||
|                     return tr.requestATheme.SetClass("block text-base mx-10 my-3").Render(); | ||||
|                 } | ||||
|                 return new SubtleButton(Svg.pencil_ui(), tr.createYourOwnTheme, { | ||||
|                     url: "./customGenerator.html", | ||||
|                     newTab: false | ||||
|                 }).Render(); | ||||
|             }) | ||||
|         )); | ||||
| 
 | ||||
|         els.push(new Combine(linkButton)) | ||||
| 
 | ||||
| 
 | ||||
|         const customThemesNames = State.state.installedThemes.data ?? []; | ||||
| 
 | ||||
|         if (customThemesNames.length > 0) { | ||||
|             els.push(Translations.t.general.customThemeIntro) | ||||
| 
 | ||||
|             for (const installed of State.state.installedThemes.data) { | ||||
|                 els.push(this.createLinkButton(installed.layout, installed.definition)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         let intro : UIElement= tr.intro; | ||||
|         if(this._onMainScreen){ | ||||
|            intro = new Combine([ | ||||
| 
 | ||||
|            LanguagePicker.CreateLanguagePicker(Translations.t.index.title.SupportedLanguages()) | ||||
|                .SetClass("absolute top-2 right-3 dropdown-ui-element-2226"), | ||||
|                new IndexText() | ||||
|                     | ||||
|                     | ||||
|            ]) | ||||
|         } | ||||
| 
 | ||||
|         this._component = new Combine([ | ||||
|             intro, | ||||
|             new Combine(els), | ||||
|             tr.streetcomplete.SetClass("block text-base mx-10 my-3 mb-10") | ||||
|         ]); | ||||
|         return this._component.Render(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										1
									
								
								index.ts
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								index.ts
									
										
									
									
									
								
							|  | @ -149,6 +149,7 @@ if (layoutFromBase64.startsWith("http")) { | |||
|     InitUiElements.InitAll(layoutToUse, layoutFromBase64, testing, defaultLayout); | ||||
| } else { | ||||
|     // We fall through: no theme loaded: just show an overview of layouts
 | ||||
|     new FixedUiElement("").AttachTo("centermessage") | ||||
|     State.state = new State(undefined); | ||||
|     new Combine([new MoreScreen(true), | ||||
|         Translations.t.general.aboutMapcomplete.SetClass("link-underline") | ||||
|  |  | |||
|  | @ -102,7 +102,7 @@ | |||
|         }, | ||||
|         "morescreen": { | ||||
|             "intro": "<h3>More thematic maps?</h3>Do you enjoy collecting geodata? <br/>There are more themes available.", | ||||
|             "requestATheme": "If you want a custom-built quest, request it <a href='https://github.com/pietervdvn/MapComplete/issues' class='underline hover:text-blue-800' target='_blank'>here</a>.", | ||||
|             "requestATheme": "If you want a custom-built quest, request it in the issue tracker", | ||||
|             "streetcomplete": "Another, similar application is <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' class='underline hover:text-blue-800' class='underline hover:text-blue-800' target='_blank'>StreetComplete</a>.", | ||||
|             "createYourOwnTheme": "Create your own MapComplete theme from scratch" | ||||
|         }, | ||||
|  |  | |||
|  | @ -102,7 +102,7 @@ | |||
|         }, | ||||
|         "morescreen": { | ||||
|             "intro": "<h3>Meer thematische kaarten</h3>Vind je het leuk om geodata te verzamelen? <br/> Hier vind je meer kaartthemas.", | ||||
|             "requestATheme": "Wil je een eigen kaartthema, vraag dit <a href='https://github.com/pietervdvn/MapComplete/issues' class='underline hover:text-blue-800' target='_blank'>hier aan</a>.", | ||||
|             "requestATheme": "Wil je een eigen kaartthema, vraag dit in de issue tracker.", | ||||
|             "streetcomplete": "Een andere, gelijkaardige Android-applicatie is <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' class='underline hover:text-blue-800' target='_blank'>StreetComplete</a>.", | ||||
|             "createYourOwnTheme": "Maak je eigen MapComplete-kaart" | ||||
|         }, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue