forked from MapComplete/MapComplete
		
	User flow improvements for the theme introduction panel
This commit is contained in:
		
							parent
							
								
									b4f739e506
								
							
						
					
					
						commit
						98866b4a57
					
				
					 10 changed files with 156 additions and 62 deletions
				
			
		| 
						 | 
				
			
			@ -62,7 +62,7 @@ export class OsmConnection {
 | 
			
		|||
    private readonly _singlePage: boolean
 | 
			
		||||
    private isChecking = false
 | 
			
		||||
 | 
			
		||||
    constructor(options: {
 | 
			
		||||
    constructor(options?: {
 | 
			
		||||
        dryRun?: UIEventSource<boolean>
 | 
			
		||||
        fakeUser?: false | boolean
 | 
			
		||||
        oauth_token?: UIEventSource<string>
 | 
			
		||||
| 
						 | 
				
			
			@ -71,6 +71,7 @@ export class OsmConnection {
 | 
			
		|||
        osmConfiguration?: "osm" | "osm-test"
 | 
			
		||||
        attemptLogin?: true | boolean
 | 
			
		||||
    }) {
 | 
			
		||||
        options = options ?? {}
 | 
			
		||||
        this.fakeUser = options.fakeUser ?? false
 | 
			
		||||
        this._singlePage = options.singlePage ?? true
 | 
			
		||||
        this._oauth_config =
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -230,10 +230,12 @@ export abstract class Store<T> {
 | 
			
		|||
 | 
			
		||||
        const newSource = new UIEventSource<T>(this.data)
 | 
			
		||||
 | 
			
		||||
        const self = this
 | 
			
		||||
        this.addCallback((latestData) => {
 | 
			
		||||
            window.setTimeout(() => {
 | 
			
		||||
                if (this.data == latestData) {
 | 
			
		||||
                    // compare by reference
 | 
			
		||||
                if (self.data == latestData) {
 | 
			
		||||
                    // compare by reference.
 | 
			
		||||
                    // Note that 'latestData' and 'self.data' are both from the same UIEVentSource, but both are dereferenced at a different time
 | 
			
		||||
                    newSource.setData(latestData)
 | 
			
		||||
                }
 | 
			
		||||
            }, millisToStabilize)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,12 +37,13 @@ export default class FullWelcomePaneWithTabs extends ScrollableFullScreen {
 | 
			
		|||
            featurePipeline: FeaturePipeline
 | 
			
		||||
            backgroundLayer: UIEventSource<BaseLayer>
 | 
			
		||||
            filteredLayers: UIEventSource<FilteredLayer[]>
 | 
			
		||||
        } & UserRelatedState
 | 
			
		||||
        } & UserRelatedState,
 | 
			
		||||
        guistate?: { userInfoIsOpened: UIEventSource<boolean> }
 | 
			
		||||
    ) {
 | 
			
		||||
        const layoutToUse = state.layoutToUse
 | 
			
		||||
        super(
 | 
			
		||||
            () => layoutToUse.title.Clone(),
 | 
			
		||||
            () => FullWelcomePaneWithTabs.GenerateContents(state, currentTab, isShown),
 | 
			
		||||
            () => FullWelcomePaneWithTabs.GenerateContents(state, currentTab, isShown, guistate),
 | 
			
		||||
            "welcome",
 | 
			
		||||
            isShown
 | 
			
		||||
        )
 | 
			
		||||
| 
						 | 
				
			
			@ -60,12 +61,13 @@ export default class FullWelcomePaneWithTabs extends ScrollableFullScreen {
 | 
			
		|||
            filteredLayers: UIEventSource<FilteredLayer[]>
 | 
			
		||||
        } & UserRelatedState,
 | 
			
		||||
        isShown: UIEventSource<boolean>,
 | 
			
		||||
        currentTab: UIEventSource<number>
 | 
			
		||||
        currentTab: UIEventSource<number>,
 | 
			
		||||
        guistate?: { userInfoIsOpened: UIEventSource<boolean> }
 | 
			
		||||
    ): { header: string | BaseUIElement; content: BaseUIElement }[] {
 | 
			
		||||
        const tabs: { header: string | BaseUIElement; content: BaseUIElement }[] = [
 | 
			
		||||
            {
 | 
			
		||||
                header: `<img src='${state.layoutToUse.icon}'>`,
 | 
			
		||||
                content: new ThemeIntroductionPanel(isShown, currentTab, state),
 | 
			
		||||
                content: new ThemeIntroductionPanel(isShown, currentTab, state, guistate),
 | 
			
		||||
            },
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -113,11 +115,12 @@ export default class FullWelcomePaneWithTabs extends ScrollableFullScreen {
 | 
			
		|||
            filteredLayers: UIEventSource<FilteredLayer[]>
 | 
			
		||||
        } & UserRelatedState,
 | 
			
		||||
        currentTab: UIEventSource<number>,
 | 
			
		||||
        isShown: UIEventSource<boolean>
 | 
			
		||||
        isShown: UIEventSource<boolean>,
 | 
			
		||||
        guistate?: { userInfoIsOpened: UIEventSource<boolean> }
 | 
			
		||||
    ) {
 | 
			
		||||
        const tabs = FullWelcomePaneWithTabs.ConstructBaseTabs(state, isShown, currentTab)
 | 
			
		||||
        const tabs = FullWelcomePaneWithTabs.ConstructBaseTabs(state, isShown, currentTab, guistate)
 | 
			
		||||
        const tabsWithAboutMc = [
 | 
			
		||||
            ...FullWelcomePaneWithTabs.ConstructBaseTabs(state, isShown, currentTab),
 | 
			
		||||
            ...FullWelcomePaneWithTabs.ConstructBaseTabs(state, isShown, currentTab, guistate),
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        tabsWithAboutMc.push({
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ import Svg from "../../Svg"
 | 
			
		|||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
 | 
			
		||||
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
 | 
			
		||||
import FullWelcomePaneWithTabs from "./FullWelcomePaneWithTabs"
 | 
			
		||||
import LoggedInUserIndicator from "../LoggedInUserIndicator"
 | 
			
		||||
 | 
			
		||||
export default class ThemeIntroductionPanel extends Combine {
 | 
			
		||||
    constructor(
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +21,8 @@ export default class ThemeIntroductionPanel extends Combine {
 | 
			
		|||
            featureSwitchUserbadge: UIEventSource<boolean>
 | 
			
		||||
            layoutToUse: LayoutConfig
 | 
			
		||||
            osmConnection: OsmConnection
 | 
			
		||||
        }
 | 
			
		||||
        },
 | 
			
		||||
        guistate?: { userInfoIsOpened: UIEventSource<boolean> }
 | 
			
		||||
    ) {
 | 
			
		||||
        const t = Translations.t.general
 | 
			
		||||
        const layout = state.layoutToUse
 | 
			
		||||
| 
						 | 
				
			
			@ -36,9 +38,18 @@ export default class ThemeIntroductionPanel extends Combine {
 | 
			
		|||
            })
 | 
			
		||||
            .SetClass("only-on-mobile")
 | 
			
		||||
 | 
			
		||||
        const loggedInUserInfo = new LoggedInUserIndicator(state.osmConnection, {
 | 
			
		||||
            firstLine: Translations.t.general.welcomeBack.Clone(),
 | 
			
		||||
        })
 | 
			
		||||
        if (guistate?.userInfoIsOpened) {
 | 
			
		||||
            loggedInUserInfo.onClick(() => {
 | 
			
		||||
                guistate.userInfoIsOpened.setData(true)
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const loginStatus = new Toggle(
 | 
			
		||||
            new LoginToggle(
 | 
			
		||||
                undefined,
 | 
			
		||||
                loggedInUserInfo,
 | 
			
		||||
                new Combine([
 | 
			
		||||
                    Translations.t.general.loginWithOpenStreetMap.SetClass("text-xl font-bold"),
 | 
			
		||||
                    Translations.t.general.loginOnlyNeededToEdit.Clone().SetClass("font-bold"),
 | 
			
		||||
| 
						 | 
				
			
			@ -60,7 +71,7 @@ export default class ThemeIntroductionPanel extends Combine {
 | 
			
		|||
            ]).SetClass("flex flex-col mt-2"),
 | 
			
		||||
 | 
			
		||||
            toTheMap,
 | 
			
		||||
            loginStatus.SetClass("block"),
 | 
			
		||||
            loginStatus.SetClass("block mt-6 pt-2 md:border-t-2 border-dotted border-gray-400"),
 | 
			
		||||
            layout.descriptionTail?.Clone().SetClass("block mt-4"),
 | 
			
		||||
 | 
			
		||||
            languagePicker?.SetClass("block mt-4"),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -140,12 +140,17 @@ class UserInformationMainPanel extends Combine {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
export default class UserInformationPanel extends ScrollableFullScreen {
 | 
			
		||||
    constructor(state: {
 | 
			
		||||
    constructor(
 | 
			
		||||
        state: {
 | 
			
		||||
            layoutToUse: LayoutConfig
 | 
			
		||||
            osmConnection: OsmConnection
 | 
			
		||||
            locationControl: UIEventSource<Loc>
 | 
			
		||||
    }) {
 | 
			
		||||
        const isOpened = new UIEventSource<boolean>(false)
 | 
			
		||||
        },
 | 
			
		||||
        options?: {
 | 
			
		||||
            isOpened?: UIEventSource<boolean>
 | 
			
		||||
        }
 | 
			
		||||
    ) {
 | 
			
		||||
        const isOpened = options?.isOpened ?? new UIEventSource<boolean>(false)
 | 
			
		||||
        super(
 | 
			
		||||
            () => {
 | 
			
		||||
                return new VariableUiElement(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,7 +33,6 @@ import GeoLocationHandler from "../Logic/Actors/GeoLocationHandler"
 | 
			
		|||
import { GeoLocationState } from "../Logic/State/GeoLocationState"
 | 
			
		||||
import Hotkeys from "./Base/Hotkeys"
 | 
			
		||||
import AvailableBaseLayers from "../Logic/Actors/AvailableBaseLayers"
 | 
			
		||||
import { Translation } from "./i18n/Translation"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The default MapComplete GUI initializer
 | 
			
		||||
| 
						 | 
				
			
			@ -205,7 +204,9 @@ export default class DefaultGUI {
 | 
			
		|||
        const self = this
 | 
			
		||||
        new Combine([
 | 
			
		||||
            Toggle.If(state.featureSwitchUserbadge, () => {
 | 
			
		||||
                const userInfo = new UserInformationPanel(state)
 | 
			
		||||
                const userInfo = new UserInformationPanel(state, {
 | 
			
		||||
                    isOpened: guiState.userInfoIsOpened,
 | 
			
		||||
                })
 | 
			
		||||
 | 
			
		||||
                const mapControl = new MapControlButton(
 | 
			
		||||
                    new VariableUiElement(
 | 
			
		||||
| 
						 | 
				
			
			@ -219,7 +220,7 @@ export default class DefaultGUI {
 | 
			
		|||
                    {
 | 
			
		||||
                        dontStyle: true,
 | 
			
		||||
                    }
 | 
			
		||||
                ).onClick(() => userInfo.Activate())
 | 
			
		||||
                ).onClick(() => guiState.userInfoIsOpened.setData(true))
 | 
			
		||||
 | 
			
		||||
                return new LoginToggle(
 | 
			
		||||
                    mapControl,
 | 
			
		||||
| 
						 | 
				
			
			@ -292,7 +293,12 @@ export default class DefaultGUI {
 | 
			
		|||
 | 
			
		||||
    private InitWelcomeMessage(): BaseUIElement {
 | 
			
		||||
        const isOpened = this.guiState.welcomeMessageIsOpened
 | 
			
		||||
        new FullWelcomePaneWithTabs(isOpened, this.guiState.welcomeMessageOpenedTab, this.state)
 | 
			
		||||
        new FullWelcomePaneWithTabs(
 | 
			
		||||
            isOpened,
 | 
			
		||||
            this.guiState.welcomeMessageOpenedTab,
 | 
			
		||||
            this.state,
 | 
			
		||||
            this.guiState
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        // ?-Button on Desktop, opens panel with close-X.
 | 
			
		||||
        const help = new MapControlButton(Svg.help_svg())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ export class DefaultGuiState {
 | 
			
		|||
    public readonly filterViewIsOpened: UIEventSource<boolean>
 | 
			
		||||
    public readonly copyrightViewIsOpened: UIEventSource<boolean>
 | 
			
		||||
    public readonly currentViewControlIsOpened: UIEventSource<boolean>
 | 
			
		||||
    public readonly userInfoIsOpened: UIEventSource<boolean>
 | 
			
		||||
    public readonly welcomeMessageOpenedTab: UIEventSource<number>
 | 
			
		||||
    public readonly allFullScreenStates: UIEventSource<boolean>[] = []
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -43,8 +44,14 @@ export class DefaultGuiState {
 | 
			
		|||
        this.currentViewControlIsOpened = QueryParameters.GetBooleanQueryParameter(
 | 
			
		||||
            "currentview-toggle",
 | 
			
		||||
            false,
 | 
			
		||||
            "Whether or not the current view box is shown"
 | 
			
		||||
            "Whether or not the current view box is shown (metalayer showing current view, allows to do calculate stats for all in view)"
 | 
			
		||||
        )
 | 
			
		||||
        this.userInfoIsOpened = QueryParameters.GetBooleanQueryParameter(
 | 
			
		||||
            "userinfo-toggle",
 | 
			
		||||
            false,
 | 
			
		||||
            "Whether or not the user info is shown"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        const states = {
 | 
			
		||||
            download: this.downloadControlIsOpened,
 | 
			
		||||
            filters: this.filterViewIsOpened,
 | 
			
		||||
| 
						 | 
				
			
			@ -66,7 +73,8 @@ export class DefaultGuiState {
 | 
			
		|||
            this.filterViewIsOpened,
 | 
			
		||||
            this.copyrightViewIsOpened,
 | 
			
		||||
            this.welcomeMessageIsOpened,
 | 
			
		||||
            this.currentViewControlIsOpened
 | 
			
		||||
            this.currentViewControlIsOpened,
 | 
			
		||||
            this.userInfoIsOpened
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this.allFullScreenStates.length; i++) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										42
									
								
								UI/LoggedInUserIndicator.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								UI/LoggedInUserIndicator.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
import { VariableUiElement } from "./Base/VariableUIElement"
 | 
			
		||||
import { OsmConnection } from "../Logic/Osm/OsmConnection"
 | 
			
		||||
import Svg from "../Svg"
 | 
			
		||||
import Img from "./Base/Img"
 | 
			
		||||
import Combine from "./Base/Combine"
 | 
			
		||||
import { FixedUiElement } from "./Base/FixedUiElement"
 | 
			
		||||
import BaseUIElement from "./BaseUIElement"
 | 
			
		||||
 | 
			
		||||
export default class LoggedInUserIndicator extends VariableUiElement {
 | 
			
		||||
    constructor(
 | 
			
		||||
        osmConnection: OsmConnection,
 | 
			
		||||
        options?: {
 | 
			
		||||
            size?: "small" | "medium" | "large"
 | 
			
		||||
            firstLine?: BaseUIElement
 | 
			
		||||
        }
 | 
			
		||||
    ) {
 | 
			
		||||
        options = options ?? {}
 | 
			
		||||
        let size = "w-8 h-8 mr-2"
 | 
			
		||||
        if (options.size == "medium") {
 | 
			
		||||
            size = "w-16 h-16 mr-4"
 | 
			
		||||
        } else if (options.size == "large") {
 | 
			
		||||
            size = "w-32 h-32 mr-6"
 | 
			
		||||
        }
 | 
			
		||||
        super(
 | 
			
		||||
            osmConnection.userDetails.mapD((ud) => {
 | 
			
		||||
                let img = Svg.person_svg().SetClass(
 | 
			
		||||
                    "rounded-full border border-black overflow-hidden"
 | 
			
		||||
                )
 | 
			
		||||
                if (ud.img) {
 | 
			
		||||
                    img = new Img(ud.img)
 | 
			
		||||
                }
 | 
			
		||||
                let contents: BaseUIElement = new FixedUiElement(ud.name).SetClass("font-bold")
 | 
			
		||||
                if (options?.firstLine) {
 | 
			
		||||
                    contents = new Combine([options.firstLine, contents]).SetClass("flex flex-col")
 | 
			
		||||
                }
 | 
			
		||||
                return new Combine([img.SetClass("rounded-full " + size), contents]).SetClass(
 | 
			
		||||
                    "flex items-center"
 | 
			
		||||
                )
 | 
			
		||||
            })
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -624,6 +624,10 @@ video {
 | 
			
		|||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.\!relative {
 | 
			
		||||
  position: relative !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.sticky {
 | 
			
		||||
  position: -webkit-sticky;
 | 
			
		||||
  position: sticky;
 | 
			
		||||
| 
						 | 
				
			
			@ -807,18 +811,22 @@ video {
 | 
			
		|||
  margin-top: 0.25rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mt-4 {
 | 
			
		||||
  margin-top: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ml-3 {
 | 
			
		||||
  margin-left: 0.75rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mr-2 {
 | 
			
		||||
  margin-right: 0.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mr-4 {
 | 
			
		||||
  margin-right: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mr-6 {
 | 
			
		||||
  margin-right: 1.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mt-4 {
 | 
			
		||||
  margin-top: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ml-4 {
 | 
			
		||||
  margin-left: 1rem;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -827,10 +835,6 @@ video {
 | 
			
		|||
  margin-bottom: 6rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mr-4 {
 | 
			
		||||
  margin-right: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mb-2 {
 | 
			
		||||
  margin-bottom: 0.5rem;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -839,6 +843,10 @@ video {
 | 
			
		|||
  margin-left: 0.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ml-3 {
 | 
			
		||||
  margin-left: 0.75rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ml-12 {
 | 
			
		||||
  margin-left: 3rem;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -960,6 +968,18 @@ video {
 | 
			
		|||
  height: 16rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.h-8 {
 | 
			
		||||
  height: 2rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.h-16 {
 | 
			
		||||
  height: 4rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.h-32 {
 | 
			
		||||
  height: 8rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.h-10 {
 | 
			
		||||
  height: 2.5rem;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -988,22 +1008,10 @@ video {
 | 
			
		|||
  height: 1.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.h-8 {
 | 
			
		||||
  height: 2rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.h-32 {
 | 
			
		||||
  height: 8rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.h-96 {
 | 
			
		||||
  height: 24rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.h-16 {
 | 
			
		||||
  height: 4rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.h-0 {
 | 
			
		||||
  height: 0px;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1048,6 +1056,18 @@ video {
 | 
			
		|||
  width: 1.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.w-8 {
 | 
			
		||||
  width: 2rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.w-16 {
 | 
			
		||||
  width: 4rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.w-32 {
 | 
			
		||||
  width: 8rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.w-10 {
 | 
			
		||||
  width: 2.5rem;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1072,10 +1092,6 @@ video {
 | 
			
		|||
  width: 2.75rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.w-8 {
 | 
			
		||||
  width: 2rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.w-min {
 | 
			
		||||
  width: -webkit-min-content;
 | 
			
		||||
  width: min-content;
 | 
			
		||||
| 
						 | 
				
			
			@ -1090,14 +1106,6 @@ video {
 | 
			
		|||
  width: 24rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.w-32 {
 | 
			
		||||
  width: 8rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.w-16 {
 | 
			
		||||
  width: 4rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.w-auto {
 | 
			
		||||
  width: auto;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1374,6 +1382,10 @@ video {
 | 
			
		|||
  border-bottom-width: 1px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.border-dotted {
 | 
			
		||||
  border-style: dotted;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.border-black {
 | 
			
		||||
  --tw-border-opacity: 1;
 | 
			
		||||
  border-color: rgb(0 0 0 / var(--tw-border-opacity));
 | 
			
		||||
| 
						 | 
				
			
			@ -2738,6 +2750,10 @@ input {
 | 
			
		|||
    border-radius: 0.75rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .md\:border-t-2 {
 | 
			
		||||
    border-top-width: 2px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .md\:p-1 {
 | 
			
		||||
    padding: 0.25rem;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -327,7 +327,7 @@
 | 
			
		|||
            "tuesday": "Tuesday",
 | 
			
		||||
            "wednesday": "Wednesday"
 | 
			
		||||
        },
 | 
			
		||||
        "welcomeBack": "You are logged in, welcome back!",
 | 
			
		||||
        "welcomeBack": "Welcome back!",
 | 
			
		||||
        "welcomeExplanation": {
 | 
			
		||||
            "addNew": "Tap the map to add a new POI.",
 | 
			
		||||
            "browseMoreMaps": "Discover more maps",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue