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"; | import {FixedUiElement} from "./FixedUiElement"; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| export class SubtleButton extends UIElement{ | export class SubtleButton extends Combine { | ||||||
|     private readonly image: UIElement; |  | ||||||
|     private readonly message: UIElement; |  | ||||||
|     private readonly linkTo: { url: string, newTab?: boolean } = undefined; |  | ||||||
| 
 | 
 | ||||||
|     constructor(imageUrl: string | UIElement, message: string | UIElement, linkTo: { url: string, newTab?: boolean } = undefined) { |     constructor(imageUrl: string | UIElement, message: string | UIElement, linkTo: { url: string, newTab?: boolean } = undefined) { | ||||||
|         super(undefined); |         super(SubtleButton.generateContent(imageUrl, message, linkTo)); | ||||||
|         this.linkTo = linkTo; | 
 | ||||||
|         this.message = Translations.W(message); |         this.SetClass("block flex p-3 my-2 bg-blue-100 rounded-lg hover:shadow-xl hover:bg-blue-200 link-no-underline") | ||||||
|         if(this.message !== null){ | 
 | ||||||
|             this.message.dumbMode = false; |     } | ||||||
|  | 
 | ||||||
|  |     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; |         let img; | ||||||
|         if ((imageUrl ?? "") === "") { |         if ((imageUrl ?? "") === "") { | ||||||
|  | @ -25,35 +27,31 @@ export class SubtleButton extends UIElement{ | ||||||
|             img = imageUrl; |             img = imageUrl; | ||||||
|         } |         } | ||||||
|         img.SetClass("block flex items-center justify-center h-11 w-11 flex-shrink0") |         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"); |             .SetClass("flex-shrink-0"); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     } |         if (message !== null && message.IsEmpty()) { | ||||||
| 
 |  | ||||||
|     InnerRender(): string { |  | ||||||
| 
 |  | ||||||
|         if(this.message !== null && this.message.IsEmpty()){ |  | ||||||
|             // Message == null: special case to force empty text
 |             // Message == null: special case to force empty text
 | ||||||
|             return ""; |             return []; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if(this.linkTo != undefined){ |         if (linkTo != undefined) { | ||||||
|             return new Combine([ |             return [ | ||||||
|                 `<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"' : ""}>`, |                 `<a class='flex group' href="${linkTo.url}" ${linkTo.newTab ? 'target="_blank"' : ""}>`, | ||||||
|                 this.image, |                 image, | ||||||
|                 `<div class='ml-4'>`, |                 `<div class='ml-4 overflow-ellipsis'>`, | ||||||
|                 this.message, |                 message, | ||||||
|                 `</div>`, |                 `</div>`, | ||||||
|                 `</a>` |                 `</a>` | ||||||
|             ]).Render(); |             ]; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return new Combine([ |         return [ | ||||||
|             this.image, |             image, | ||||||
|             this.message, |             message, | ||||||
|         ]).SetClass("block flex p-3 my-2 bg-blue-100 rounded-lg hover:shadow-xl hover:bg-blue-200 link-no-underline") |         ]; | ||||||
|             .Render(); | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -25,12 +25,78 @@ export default class MoreScreen extends UIElement { | ||||||
|         this.ListenTo(State.state.installedThemes); |         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) { |     private createLinkButton(layout: LayoutConfig, customThemeDefinition: string = undefined) { | ||||||
|         if (layout === undefined) { |         if (layout === undefined) { | ||||||
|             return undefined; |             return undefined; | ||||||
|         } |         } | ||||||
|         if(layout.id === undefined){ |         if (layout.id === undefined) { | ||||||
|             console.error("ID is undefined for layout",layout); |             console.error("ID is undefined for layout", layout); | ||||||
|             return undefined; |             return undefined; | ||||||
|         } |         } | ||||||
|         if (layout.hideFromOverview) { |         if (layout.hideFromOverview) { | ||||||
|  | @ -49,7 +115,7 @@ export default class MoreScreen extends UIElement { | ||||||
|         // Path starts with a '/' and contains everything, e.g. '/dir/dir/page.html'
 |         // Path starts with a '/' and contains everything, e.g. '/dir/dir/page.html'
 | ||||||
|         path = path.substr(0, path.lastIndexOf("/")); |         path = path.substr(0, path.lastIndexOf("/")); | ||||||
|         // Path will now contain '/dir/dir', or empty string in case of nothing
 |         // Path will now contain '/dir/dir', or empty string in case of nothing
 | ||||||
|         if(path === ""){ |         if (path === "") { | ||||||
|             path = "." |             path = "." | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -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'>`, |                 `<dt class='text-lg leading-6 font-medium text-gray-900 group-hover:text-blue-800'>`, | ||||||
|                 Translations.W(layout.title), |                 Translations.W(layout.title), | ||||||
|                 `</dt>`, |                 `</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 ?? "", |                 description ?? "", | ||||||
|                 `</dd>`, |                 `</dd>`, | ||||||
|             ]), {url: linkText, newTab: false}); |             ]), {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); |     InitUiElements.InitAll(layoutToUse, layoutFromBase64, testing, defaultLayout); | ||||||
| } else { | } else { | ||||||
|     // We fall through: no theme loaded: just show an overview of layouts
 |     // We fall through: no theme loaded: just show an overview of layouts
 | ||||||
|  |     new FixedUiElement("").AttachTo("centermessage") | ||||||
|     State.state = new State(undefined); |     State.state = new State(undefined); | ||||||
|     new Combine([new MoreScreen(true), |     new Combine([new MoreScreen(true), | ||||||
|         Translations.t.general.aboutMapcomplete.SetClass("link-underline") |         Translations.t.general.aboutMapcomplete.SetClass("link-underline") | ||||||
|  |  | ||||||
|  | @ -102,7 +102,7 @@ | ||||||
|         }, |         }, | ||||||
|         "morescreen": { |         "morescreen": { | ||||||
|             "intro": "<h3>More thematic maps?</h3>Do you enjoy collecting geodata? <br/>There are more themes available.", |             "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>.", |             "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" |             "createYourOwnTheme": "Create your own MapComplete theme from scratch" | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|  | @ -102,7 +102,7 @@ | ||||||
|         }, |         }, | ||||||
|         "morescreen": { |         "morescreen": { | ||||||
|             "intro": "<h3>Meer thematische kaarten</h3>Vind je het leuk om geodata te verzamelen? <br/> Hier vind je meer kaartthemas.", |             "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>.", |             "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" |             "createYourOwnTheme": "Maak je eigen MapComplete-kaart" | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue