forked from MapComplete/MapComplete
refactoring: Remove more obsoleted code, add copyright tab
This commit is contained in:
parent
f8d34648a0
commit
042d400dc4
20 changed files with 44 additions and 342 deletions
|
@ -1,25 +0,0 @@
|
||||||
import { UIEventSource } from "../UIEventSource"
|
|
||||||
import FilteredLayer from "../../Models/FilteredLayer"
|
|
||||||
import ScrollableFullScreen from "../../UI/Base/ScrollableFullScreen"
|
|
||||||
import BaseUIElement from "../../UI/BaseUIElement"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The stray-click-handler adds a marker to the map if no feature was clicked.
|
|
||||||
* Shows the given uiToShow-element in the messagebox
|
|
||||||
*
|
|
||||||
* Note: the actual implementation is in StrayClickHandlerImplementation
|
|
||||||
*/
|
|
||||||
export default class StrayClickHandler {
|
|
||||||
public static construct = (
|
|
||||||
state: {
|
|
||||||
LastClickLocation: UIEventSource<{ lat: number; lon: number }>
|
|
||||||
selectedElement: UIEventSource<string>
|
|
||||||
filteredLayers: UIEventSource<FilteredLayer[]>
|
|
||||||
leafletMap: UIEventSource<any>
|
|
||||||
},
|
|
||||||
uiToShow: ScrollableFullScreen,
|
|
||||||
iconToShow: BaseUIElement
|
|
||||||
) => {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,13 +11,13 @@ export default class ContributorCount {
|
||||||
private lastUpdate: Date = undefined
|
private lastUpdate: Date = undefined
|
||||||
|
|
||||||
constructor(state: {
|
constructor(state: {
|
||||||
bounds: Store<BBox>
|
mapProperties: { bounds: Store<BBox> }
|
||||||
dataIsLoading: Store<boolean>
|
dataIsLoading: Store<boolean>
|
||||||
perLayer: ReadonlyMap<string, GeoIndexedStore>
|
perLayer: ReadonlyMap<string, GeoIndexedStore>
|
||||||
}) {
|
}) {
|
||||||
this.perLayer = state.perLayer
|
this.perLayer = state.perLayer
|
||||||
const self = this
|
const self = this
|
||||||
state.bounds.mapD(
|
state.mapProperties.bounds.mapD(
|
||||||
(bbox) => {
|
(bbox) => {
|
||||||
self.update(bbox)
|
self.update(bbox)
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { FeatureSource , FeatureSourceForLayer } from "../FeatureSource"
|
import { FeatureSource, FeatureSourceForLayer } from "../FeatureSource"
|
||||||
import { Feature } from "geojson"
|
import { Feature } from "geojson"
|
||||||
import { BBox } from "../../BBox"
|
import { BBox } from "../../BBox"
|
||||||
import { GeoOperations } from "../../GeoOperations"
|
import { GeoOperations } from "../../GeoOperations"
|
||||||
|
@ -26,9 +26,12 @@ export default class GeoIndexedStore implements FeatureSource {
|
||||||
public GetFeaturesWithin(bbox: BBox): Feature[] {
|
public GetFeaturesWithin(bbox: BBox): Feature[] {
|
||||||
// TODO optimize
|
// TODO optimize
|
||||||
const bboxFeature = bbox.asGeoJson({})
|
const bboxFeature = bbox.asGeoJson({})
|
||||||
return this.features.data.filter(
|
return this.features.data.filter((f) => {
|
||||||
(f) => GeoOperations.intersect(f, bboxFeature) !== undefined
|
if (f.geometry.type === "Point") {
|
||||||
)
|
return bbox.contains(<[number, number]>f.geometry.coordinates)
|
||||||
|
}
|
||||||
|
return GeoOperations.intersect(f, bboxFeature) !== undefined
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
import SelectedFeatureHandler from "../Actors/SelectedFeatureHandler"
|
|
||||||
import Hash from "../Web/Hash"
|
|
||||||
import MetaTagRecalculator from "../FeatureSource/Actors/MetaTagRecalculator"
|
|
||||||
|
|
||||||
export default class FeaturePipelineState {
|
|
||||||
/**
|
|
||||||
* The piece of code which fetches data from various sources and shows it on the background map
|
|
||||||
*/
|
|
||||||
public readonly featurePipeline: FeaturePipeline
|
|
||||||
private readonly metatagRecalculator: MetaTagRecalculator
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.metatagRecalculator = new MetaTagRecalculator(this, this.featurePipeline)
|
|
||||||
this.metatagRecalculator.registerSource(this.currentView)
|
|
||||||
new SelectedFeatureHandler(Hash.hash, this)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -244,7 +244,7 @@ export class RegexTag extends TagsFilter {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
asChange(properties: Record<string, string>): { k: string; v: string }[] {
|
asChange(): { k: string; v: string }[] {
|
||||||
if (this.invert) {
|
if (this.invert) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,6 +222,14 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
/*
|
||||||
|
Hotkeys.RegisterHotkey(
|
||||||
|
{ shift: "O" },
|
||||||
|
Translations.t.hotkeyDocumentation.selectMapnik,
|
||||||
|
() => {
|
||||||
|
this.state.backgroundLayer.setData(AvailableBaseLayers.osmCarto)
|
||||||
|
}
|
||||||
|
)//*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -107,9 +107,6 @@ export default class ScrollableFullScreen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Destroy() {
|
|
||||||
this._fullscreencomponent.Destroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actually show this in the 'fullscreen'-div
|
* Actually show this in the 'fullscreen'-div
|
||||||
|
@ -163,7 +160,4 @@ export default class ScrollableFullScreen {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
static ActivateCurrent() {
|
|
||||||
ScrollableFullScreen._currentlyOpen?.Activate()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,9 @@ import BaseUIElement from "../BaseUIElement"
|
||||||
import { VariableUiElement } from "./VariableUIElement"
|
import { VariableUiElement } from "./VariableUIElement"
|
||||||
|
|
||||||
export class TabbedComponent extends Combine {
|
export class TabbedComponent extends Combine {
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
elements: { header: BaseUIElement | string; content: BaseUIElement | string }[],
|
elements: { header: BaseUIElement | string; content: BaseUIElement | string }[],
|
||||||
openedTab: UIEventSource<number> | number = 0,
|
openedTab: UIEventSource<number> | number = 0,
|
||||||
|
|
|
@ -113,7 +113,7 @@ export default class CopyrightPanel extends Combine {
|
||||||
|
|
||||||
constructor(state: {
|
constructor(state: {
|
||||||
layout: LayoutConfig
|
layout: LayoutConfig
|
||||||
bounds: Store<BBox>
|
mapProperties: { bounds: Store<BBox> }
|
||||||
osmConnection: OsmConnection
|
osmConnection: OsmConnection
|
||||||
dataIsLoading: Store<boolean>
|
dataIsLoading: Store<boolean>
|
||||||
perLayer: ReadonlyMap<string, GeoIndexedStore>
|
perLayer: ReadonlyMap<string, GeoIndexedStore>
|
||||||
|
@ -121,7 +121,7 @@ export default class CopyrightPanel extends Combine {
|
||||||
const t = Translations.t.general.attribution
|
const t = Translations.t.general.attribution
|
||||||
const layoutToUse = state.layout
|
const layoutToUse = state.layout
|
||||||
|
|
||||||
const iconAttributions: BaseUIElement[] = layoutToUse.usedImages.map(
|
const iconAttributions: BaseUIElement[] = Utils.Dedup(layoutToUse.usedImages).map(
|
||||||
CopyrightPanel.IconAttribution
|
CopyrightPanel.IconAttribution
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
fieldTypes[field.name + "}"] = field.type;
|
fieldTypes[field.name + "}"] = field.type;
|
||||||
const src = new UIEventSource<string>(initialState[field.name] ?? "");
|
const src = new UIEventSource<string>(initialState[field.name] ?? "");
|
||||||
fieldValues[field.name + "}"] = src;
|
fieldValues[field.name + "}"] = src;
|
||||||
onDestroy(src.addCallback(v => {
|
onDestroy(src.addCallback(() => {
|
||||||
setFields();
|
setFields();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,131 +0,0 @@
|
||||||
import ThemeIntroductionPanel from "./ThemeIntroductionPanel"
|
|
||||||
import Svg from "../../Svg"
|
|
||||||
import Translations from "../i18n/Translations"
|
|
||||||
import ShareScreen from "./ShareScreen"
|
|
||||||
import MoreScreen from "./MoreScreen"
|
|
||||||
import Constants from "../../Models/Constants"
|
|
||||||
import Combine from "../Base/Combine"
|
|
||||||
import { TabbedComponent } from "../Base/TabbedComponent"
|
|
||||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
|
||||||
import UserDetails, { OsmConnection } from "../../Logic/Osm/OsmConnection"
|
|
||||||
import ScrollableFullScreen from "../Base/ScrollableFullScreen"
|
|
||||||
import BaseUIElement from "../BaseUIElement"
|
|
||||||
import Toggle from "../Input/Toggle"
|
|
||||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
|
|
||||||
import { Utils } from "../../Utils"
|
|
||||||
import UserRelatedState from "../../Logic/State/UserRelatedState"
|
|
||||||
import Loc from "../../Models/Loc"
|
|
||||||
import FilteredLayer from "../../Models/FilteredLayer"
|
|
||||||
import Hotkeys from "../Base/Hotkeys"
|
|
||||||
|
|
||||||
export default class FullWelcomePaneWithTabs extends ScrollableFullScreen {
|
|
||||||
public static MoreThemesTabIndex = 1
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
isShown: UIEventSource<boolean>,
|
|
||||||
currentTab: UIEventSource<number>,
|
|
||||||
state: {
|
|
||||||
layoutToUse: LayoutConfig
|
|
||||||
osmConnection: OsmConnection
|
|
||||||
featureSwitchShareScreen: UIEventSource<boolean>
|
|
||||||
featureSwitchMoreQuests: UIEventSource<boolean>
|
|
||||||
locationControl: UIEventSource<Loc>
|
|
||||||
featurePipeline: FeaturePipeline
|
|
||||||
backgroundLayer: UIEventSource<BaseLayer>
|
|
||||||
filteredLayers: UIEventSource<FilteredLayer[]>
|
|
||||||
} & UserRelatedState,
|
|
||||||
guistate?: { userInfoIsOpened: UIEventSource<boolean> }
|
|
||||||
) {
|
|
||||||
const layoutToUse = state.layoutToUse
|
|
||||||
super(
|
|
||||||
() => layoutToUse.title.Clone(),
|
|
||||||
() => FullWelcomePaneWithTabs.GenerateContents(state, currentTab, isShown, guistate),
|
|
||||||
"welcome",
|
|
||||||
isShown
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ConstructBaseTabs(
|
|
||||||
state: {
|
|
||||||
layoutToUse: LayoutConfig
|
|
||||||
osmConnection: OsmConnection
|
|
||||||
featureSwitchShareScreen: UIEventSource<boolean>
|
|
||||||
featureSwitchMoreQuests: UIEventSource<boolean>
|
|
||||||
featurePipeline: FeaturePipeline
|
|
||||||
locationControl: UIEventSource<Loc>
|
|
||||||
backgroundLayer: UIEventSource<BaseLayer>
|
|
||||||
filteredLayers: UIEventSource<FilteredLayer[]>
|
|
||||||
} & UserRelatedState,
|
|
||||||
isShown: UIEventSource<boolean>,
|
|
||||||
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, guistate),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
if (state.featureSwitchMoreQuests.data) {
|
|
||||||
tabs.push({
|
|
||||||
header: Svg.add_img,
|
|
||||||
content: new Combine([
|
|
||||||
Translations.t.general.morescreen.intro,
|
|
||||||
new MoreScreen(state),
|
|
||||||
]).SetClass("flex flex-col"),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.featureSwitchShareScreen.data) {
|
|
||||||
tabs.push({ header: Svg.share_img, content: new ShareScreen(state) })
|
|
||||||
}
|
|
||||||
|
|
||||||
return tabs
|
|
||||||
}
|
|
||||||
|
|
||||||
private static GenerateContents(
|
|
||||||
state: {
|
|
||||||
layoutToUse: LayoutConfig
|
|
||||||
osmConnection: OsmConnection
|
|
||||||
featureSwitchShareScreen: UIEventSource<boolean>
|
|
||||||
featureSwitchMoreQuests: UIEventSource<boolean>
|
|
||||||
featurePipeline: FeaturePipeline
|
|
||||||
locationControl: UIEventSource<Loc>
|
|
||||||
backgroundLayer: UIEventSource<BaseLayer>
|
|
||||||
filteredLayers: UIEventSource<FilteredLayer[]>
|
|
||||||
} & UserRelatedState,
|
|
||||||
currentTab: UIEventSource<number>,
|
|
||||||
isShown: UIEventSource<boolean>,
|
|
||||||
guistate?: { userInfoIsOpened: UIEventSource<boolean> }
|
|
||||||
) {
|
|
||||||
const tabs = FullWelcomePaneWithTabs.ConstructBaseTabs(state, isShown, currentTab, guistate)
|
|
||||||
const tabsWithAboutMc = [
|
|
||||||
...FullWelcomePaneWithTabs.ConstructBaseTabs(state, isShown, currentTab, guistate),
|
|
||||||
]
|
|
||||||
|
|
||||||
tabsWithAboutMc.push({
|
|
||||||
header: Svg.help,
|
|
||||||
content: new Combine([
|
|
||||||
Translations.t.general.aboutMapcomplete.Subs({
|
|
||||||
osmcha_link: Utils.OsmChaLinkFor(7),
|
|
||||||
}),
|
|
||||||
"<br/>Version " + Constants.vNumber,
|
|
||||||
Hotkeys.generateDocumentationDynamic(),
|
|
||||||
]).SetClass("link-underline"),
|
|
||||||
})
|
|
||||||
|
|
||||||
tabs.forEach((c) => c.content.SetClass("p-4"))
|
|
||||||
tabsWithAboutMc.forEach((c) => c.content.SetClass("p-4"))
|
|
||||||
|
|
||||||
return new Toggle(
|
|
||||||
new TabbedComponent(tabsWithAboutMc, currentTab),
|
|
||||||
new TabbedComponent(tabs, currentTab),
|
|
||||||
state.osmConnection.userDetails.map(
|
|
||||||
(userdetails: UserDetails) =>
|
|
||||||
userdetails.loggedIn &&
|
|
||||||
userdetails.csCount >= Constants.userJourney.mapCompleteHelpUnlock
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -33,9 +33,3 @@ export interface PresetInfo extends PresetConfig {
|
||||||
layerToAddTo: FilteredLayer
|
layerToAddTo: FilteredLayer
|
||||||
boundsFactor?: 0.25 | number
|
boundsFactor?: 0.25 | number
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class SimpleAddUI extends Combine {
|
|
||||||
constructor(state: SpecialVisualizationState) {
|
|
||||||
super([])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
143
UI/DefaultGUI.ts
143
UI/DefaultGUI.ts
|
@ -1,33 +1,15 @@
|
||||||
import FeaturePipelineState from "../Logic/State/FeaturePipelineState"
|
|
||||||
import { Utils } from "../Utils"
|
import { Utils } from "../Utils"
|
||||||
import { UIEventSource } from "../Logic/UIEventSource"
|
|
||||||
import FullWelcomePaneWithTabs from "./BigComponents/FullWelcomePaneWithTabs"
|
|
||||||
import MapControlButton from "./MapControlButton"
|
|
||||||
import Svg from "../Svg"
|
|
||||||
import Toggle from "./Input/Toggle"
|
import Toggle from "./Input/Toggle"
|
||||||
import BaseUIElement from "./BaseUIElement"
|
|
||||||
import LeftControls from "./BigComponents/LeftControls"
|
import LeftControls from "./BigComponents/LeftControls"
|
||||||
import RightControls from "./BigComponents/RightControls"
|
import RightControls from "./BigComponents/RightControls"
|
||||||
import CenterMessageBox from "./CenterMessageBox"
|
import CenterMessageBox from "./CenterMessageBox"
|
||||||
import ScrollableFullScreen from "./Base/ScrollableFullScreen"
|
import ScrollableFullScreen from "./Base/ScrollableFullScreen"
|
||||||
import Translations from "./i18n/Translations"
|
import Translations from "./i18n/Translations"
|
||||||
import SimpleAddUI from "./BigComponents/SimpleAddUI"
|
|
||||||
import StrayClickHandler from "../Logic/Actors/StrayClickHandler"
|
|
||||||
import { DefaultGuiState } from "./DefaultGuiState"
|
import { DefaultGuiState } from "./DefaultGuiState"
|
||||||
import NewNoteUi from "./Popup/NewNoteUi"
|
|
||||||
import Combine from "./Base/Combine"
|
import Combine from "./Base/Combine"
|
||||||
import FilteredLayer from "../Models/FilteredLayer"
|
|
||||||
import ExtraLinkButton from "./BigComponents/ExtraLinkButton"
|
import ExtraLinkButton from "./BigComponents/ExtraLinkButton"
|
||||||
import { VariableUiElement } from "./Base/VariableUIElement"
|
|
||||||
import Img from "./Base/Img"
|
|
||||||
import UserInformationPanel from "./BigComponents/UserInformation"
|
|
||||||
import { LoginToggle } from "./Popup/LoginButton"
|
|
||||||
import { FixedUiElement } from "./Base/FixedUiElement"
|
|
||||||
import GeoLocationHandler from "../Logic/Actors/GeoLocationHandler"
|
import GeoLocationHandler from "../Logic/Actors/GeoLocationHandler"
|
||||||
import Hotkeys from "./Base/Hotkeys"
|
|
||||||
import CopyrightPanel from "./BigComponents/CopyrightPanel"
|
import CopyrightPanel from "./BigComponents/CopyrightPanel"
|
||||||
import SvelteUIElement from "./Base/SvelteUIElement"
|
|
||||||
import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default MapComplete GUI initializer
|
* The default MapComplete GUI initializer
|
||||||
|
@ -36,17 +18,14 @@ import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte"
|
||||||
*/
|
*/
|
||||||
export default class DefaultGUI {
|
export default class DefaultGUI {
|
||||||
private readonly guiState: DefaultGuiState
|
private readonly guiState: DefaultGuiState
|
||||||
private readonly state: FeaturePipelineState
|
|
||||||
private readonly geolocationHandler: GeoLocationHandler | undefined
|
private readonly geolocationHandler: GeoLocationHandler | undefined
|
||||||
|
|
||||||
constructor(state: FeaturePipelineState, guiState: DefaultGuiState) {
|
constructor(guiState: DefaultGuiState) {
|
||||||
this.state = state
|
|
||||||
this.guiState = guiState
|
this.guiState = guiState
|
||||||
}
|
}
|
||||||
|
|
||||||
public setup() {
|
public setup() {
|
||||||
this.SetupUIElements()
|
this.SetupUIElements()
|
||||||
this.SetupMap()
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.state.layoutToUse.customCss !== undefined &&
|
this.state.layoutToUse.customCss !== undefined &&
|
||||||
|
@ -54,131 +33,24 @@ export default class DefaultGUI {
|
||||||
) {
|
) {
|
||||||
Utils.LoadCustomCss(this.state.layoutToUse.customCss)
|
Utils.LoadCustomCss(this.state.layoutToUse.customCss)
|
||||||
}
|
}
|
||||||
|
|
||||||
Hotkeys.RegisterHotkey(
|
|
||||||
{ shift: "O" },
|
|
||||||
Translations.t.hotkeyDocumentation.selectMapnik,
|
|
||||||
() => {
|
|
||||||
this.state.backgroundLayer.setData(AvailableBaseLayers.osmCarto)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
public setupClickDialogOnMap(
|
|
||||||
filterViewIsOpened: UIEventSource<boolean>,
|
|
||||||
state: FeaturePipelineState
|
|
||||||
) {
|
|
||||||
const hasPresets = state.layoutToUse.layers.some((layer) => layer.presets.length > 0)
|
|
||||||
const noteLayer: FilteredLayer = state.filteredLayers.data.filter(
|
|
||||||
(l) => l.layerDef.id === "note"
|
|
||||||
)[0]
|
|
||||||
let addNewNoteDialog: (isShown: UIEventSource<boolean>) => BaseUIElement = undefined
|
|
||||||
if (noteLayer !== undefined) {
|
|
||||||
addNewNoteDialog = (isShown) => new NewNoteUi(noteLayer, isShown, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
if (!hasPresets && addNewNoteDialog === undefined) {
|
|
||||||
return // nothing to do
|
|
||||||
}
|
|
||||||
const newPointDialogIsShown = new UIEventSource<boolean>(false)
|
|
||||||
const addNewPoint = new ScrollableFullScreen(
|
|
||||||
() =>
|
|
||||||
hasPresets
|
|
||||||
? Translations.t.general.add.title
|
|
||||||
: Translations.t.notes.createNoteTitle,
|
|
||||||
({ resetScrollSignal }) => {
|
|
||||||
let addNew = undefined
|
|
||||||
if (hasPresets) {
|
|
||||||
addNew = new SimpleAddUI(
|
|
||||||
newPointDialogIsShown,
|
|
||||||
resetScrollSignal,
|
|
||||||
filterViewIsOpened,
|
|
||||||
state
|
|
||||||
)
|
|
||||||
}
|
|
||||||
let addNote = undefined
|
|
||||||
if (noteLayer !== undefined) {
|
|
||||||
addNote = addNewNoteDialog(newPointDialogIsShown)
|
|
||||||
}
|
|
||||||
return new Combine([addNew, addNote]).SetClass("flex flex-col font-lg text-lg")
|
|
||||||
},
|
|
||||||
"new",
|
|
||||||
newPointDialogIsShown
|
|
||||||
)
|
|
||||||
|
|
||||||
let noteMarker = undefined
|
|
||||||
if (!hasPresets && addNewNoteDialog !== undefined) {
|
|
||||||
noteMarker = new Combine([
|
|
||||||
Svg.note_svg().SetClass("absolute bottom-0").SetStyle("height: 40px"),
|
|
||||||
Svg.addSmall_svg()
|
|
||||||
.SetClass("absolute w-6 animate-pulse")
|
|
||||||
.SetStyle("right: 10px; bottom: -8px;"),
|
|
||||||
])
|
|
||||||
.SetClass("block relative h-full")
|
|
||||||
.SetStyle("left: calc( 50% - 15px )") // This is a bit hacky, yes I know!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (noteLayer !== undefined) {
|
|
||||||
setup()
|
|
||||||
} else {
|
|
||||||
state.featureSwitchAddNew.addCallbackAndRunD((addNewAllowed) => {
|
|
||||||
if (addNewAllowed) {
|
|
||||||
setup()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SetupMap() {
|
|
||||||
if (Utils.runningFromConsole) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const state = this.state
|
|
||||||
const guiState = this.guiState
|
|
||||||
|
|
||||||
this.setupClickDialogOnMap(guiState.filterViewIsOpened, state)
|
|
||||||
|
|
||||||
const selectedElement: FilteredLayer = state.filteredLayers.data.filter(
|
|
||||||
(l) => l.layerDef.id === "selected_element"
|
|
||||||
)[0]
|
|
||||||
new ShowDataLayer({
|
|
||||||
leafletMap: state.leafletMap,
|
|
||||||
layerToShow: selectedElement.layerDef,
|
|
||||||
features: state.selectedElementsLayer,
|
|
||||||
state,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SetupUIElements() {
|
private SetupUIElements() {
|
||||||
const state = this.state
|
|
||||||
const guiState = this.guiState
|
const guiState = this.guiState
|
||||||
|
|
||||||
const self = this
|
|
||||||
|
|
||||||
const extraLink = Toggle.If(
|
const extraLink = Toggle.If(
|
||||||
state.featureSwitchExtraLinkEnabled,
|
state.featureSwitchExtraLinkEnabled,
|
||||||
() => new ExtraLinkButton(state, state.layoutToUse.extraLink)
|
() => new ExtraLinkButton(state, state.layoutToUse.extraLink)
|
||||||
)
|
)
|
||||||
|
|
||||||
const welcomeMessageMapControl = Toggle.If(state.featureSwitchWelcomeMessage, () =>
|
|
||||||
self.InitWelcomeMessage()
|
|
||||||
)
|
|
||||||
|
|
||||||
new ScrollableFullScreen(
|
new ScrollableFullScreen(
|
||||||
() => Translations.t.general.attribution.attributionTitle,
|
() => Translations.t.general.attribution.attributionTitle,
|
||||||
() => new CopyrightPanel(state),
|
() => new CopyrightPanel(state),
|
||||||
"copyright",
|
"copyright",
|
||||||
guiState.copyrightViewIsOpened
|
guiState.copyrightViewIsOpened
|
||||||
)
|
)
|
||||||
const copyright = new MapControlButton(Svg.copyright_svg()).onClick(() =>
|
|
||||||
guiState.copyrightViewIsOpened.setData(true)
|
new Combine([extraLink]).SetClass("flex flex-col").AttachTo("top-left")
|
||||||
)
|
|
||||||
new Combine([welcomeMessageMapControl, copyright, extraLink])
|
|
||||||
.SetClass("flex flex-col")
|
|
||||||
.AttachTo("top-left")
|
|
||||||
|
|
||||||
new Combine([
|
new Combine([
|
||||||
new ExtraLinkButton(state, {
|
new ExtraLinkButton(state, {
|
||||||
|
@ -198,13 +70,4 @@ export default class DefaultGUI {
|
||||||
new CenterMessageBox(state).AttachTo("centermessage")
|
new CenterMessageBox(state).AttachTo("centermessage")
|
||||||
document?.getElementById("centermessage")?.classList?.add("pointer-events-none")
|
document?.getElementById("centermessage")?.classList?.add("pointer-events-none")
|
||||||
}
|
}
|
||||||
|
|
||||||
private InitWelcomeMessage(): BaseUIElement {
|
|
||||||
return new FullWelcomePaneWithTabs(
|
|
||||||
new UIEventSource<boolean>(false),
|
|
||||||
this.guiState.welcomeMessageOpenedTab,
|
|
||||||
this.state,
|
|
||||||
this.guiState
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import { Store } from "../../Logic/UIEventSource"
|
||||||
|
|
||||||
export default class SingleReview extends Combine {
|
export default class SingleReview extends Combine {
|
||||||
constructor(review: Review & { madeByLoggedInUser: Store<boolean> }) {
|
constructor(review: Review & { madeByLoggedInUser: Store<boolean> }) {
|
||||||
const d = review
|
|
||||||
const date = new Date(review.iat * 1000)
|
const date = new Date(review.iat * 1000)
|
||||||
const reviewAuthor =
|
const reviewAuthor =
|
||||||
review.metadata.nickname ??
|
review.metadata.nickname ??
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
import UserRelatedState from "../Logic/State/UserRelatedState";
|
import UserRelatedState from "../Logic/State/UserRelatedState";
|
||||||
import LoginToggle from "./Base/LoginToggle.svelte";
|
import LoginToggle from "./Base/LoginToggle.svelte";
|
||||||
import LoginButton from "./Base/LoginButton.svelte";
|
import LoginButton from "./Base/LoginButton.svelte";
|
||||||
|
import CopyrightPanel from "./BigComponents/CopyrightPanel.js";
|
||||||
|
|
||||||
export let state: ThemeViewState;
|
export let state: ThemeViewState;
|
||||||
let layout = state.layout;
|
let layout = state.layout;
|
||||||
|
@ -149,6 +150,12 @@
|
||||||
<RasterLayerPicker {availableLayers} value={mapproperties.rasterLayer}></RasterLayerPicker>
|
<RasterLayerPicker {availableLayers} value={mapproperties.rasterLayer}></RasterLayerPicker>
|
||||||
</If>
|
</If>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div slot="title2">
|
||||||
|
<Tr t={Translations.t.general.attribution.title}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ToSvelte slot="content2" construct={() => new CopyrightPanel(state)}></ToSvelte>
|
||||||
</TabbedGroup>
|
</TabbedGroup>
|
||||||
</FloatOver>
|
</FloatOver>
|
||||||
</If>
|
</If>
|
||||||
|
|
6
Utils.ts
6
Utils.ts
|
@ -308,6 +308,12 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new array with all elements from 'arr' in such a way that every element will be kept only once
|
||||||
|
* Elements are returned in the same order as they appear in the lists
|
||||||
|
* @param arr
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
public static Dedup(arr: string[]): string[] {
|
public static Dedup(arr: string[]): string[] {
|
||||||
if (arr === undefined) {
|
if (arr === undefined) {
|
||||||
return undefined
|
return undefined
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
"then": {
|
"then": {
|
||||||
"special": {
|
"special": {
|
||||||
"type": "link",
|
"type": "link",
|
||||||
"href": "{_backend}/messages/inbox",
|
"href": "{_backend}/messages/inbox",
|
||||||
"text": {
|
"text": {
|
||||||
"en": "Open your inbox",
|
"en": "Open your inbox",
|
||||||
"nl": "Ga naar je inbox"
|
"nl": "Ga naar je inbox"
|
||||||
|
@ -393,4 +393,4 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"mapRendering": null
|
"mapRendering": null
|
||||||
}
|
}
|
|
@ -2019,4 +2019,4 @@
|
||||||
"pl": "Nazwa sieci to <b>{internet_access:ssid}</b>"
|
"pl": "Nazwa sieci to <b>{internet_access:ssid}</b>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -146,6 +146,7 @@
|
||||||
"openMapillary": "Open Mapillary here",
|
"openMapillary": "Open Mapillary here",
|
||||||
"openOsmcha": "See latest edits made with {theme}",
|
"openOsmcha": "See latest edits made with {theme}",
|
||||||
"themeBy": "Theme maintained by {author}",
|
"themeBy": "Theme maintained by {author}",
|
||||||
|
"title": "Copyright and attribution",
|
||||||
"translatedBy": "MapComplete has been translated by {contributors} and <a href='https://github.com/pietervdvn/MapComplete/graphs/contributors' target='_blank'>{hiddenCount} more contributors</a>"
|
"translatedBy": "MapComplete has been translated by {contributors} and <a href='https://github.com/pietervdvn/MapComplete/graphs/contributors' target='_blank'>{hiddenCount} more contributors</a>"
|
||||||
},
|
},
|
||||||
"back": "Back",
|
"back": "Back",
|
||||||
|
|
3
test.ts
3
test.ts
|
@ -15,8 +15,6 @@ async function main() {
|
||||||
const state = new ThemeViewState(layout)
|
const state = new ThemeViewState(layout)
|
||||||
|
|
||||||
const main = new SvelteUIElement(ThemeViewGUI, { state })
|
const main = new SvelteUIElement(ThemeViewGUI, { state })
|
||||||
state.guistate.menuIsOpened.setData(true)
|
|
||||||
state.guistate.menuViewTab.setData("settings")
|
|
||||||
main.AttachTo("maindiv")
|
main.AttachTo("maindiv")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +22,6 @@ async function testspecial() {
|
||||||
const layout = new LayoutConfig(<any>theme, true) // qp.data === "" ? : new AllKnownLayoutsLazy().get(qp.data)
|
const layout = new LayoutConfig(<any>theme, true) // qp.data === "" ? : new AllKnownLayoutsLazy().get(qp.data)
|
||||||
const state = new ThemeViewState(layout)
|
const state = new ThemeViewState(layout)
|
||||||
|
|
||||||
state.guistate.openUsersettings("picture-license")
|
|
||||||
const all = SpecialVisualizations.specialVisualizations.map((s) =>
|
const all = SpecialVisualizations.specialVisualizations.map((s) =>
|
||||||
SpecialVisualizations.renderExampleOfSpecial(state, s)
|
SpecialVisualizations.renderExampleOfSpecial(state, s)
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue