Lots of styling tweaks, add filter links between layers
This commit is contained in:
parent
5cefc4d25f
commit
c15f3d2036
28 changed files with 263 additions and 217 deletions
|
@ -17,6 +17,7 @@ import SimpleFeatureSource from "../FeatureSource/Sources/SimpleFeatureSource";
|
|||
import {LocalStorageSource} from "../Web/LocalStorageSource";
|
||||
import {GeoOperations} from "../GeoOperations";
|
||||
import TitleHandler from "../Actors/TitleHandler";
|
||||
import {BBox} from "../BBox";
|
||||
|
||||
/**
|
||||
* Contains all the leaflet-map related state
|
||||
|
@ -73,7 +74,7 @@ export default class MapState extends UserRelatedState {
|
|||
|
||||
|
||||
/**
|
||||
* WHich layers are enabled in the current theme
|
||||
* Which layers are enabled in the current theme and what filters are applied onto them
|
||||
*/
|
||||
public filteredLayers: UIEventSource<FilteredLayer[]> = new UIEventSource<FilteredLayer[]>([], "filteredLayers");
|
||||
/**
|
||||
|
@ -169,11 +170,10 @@ export default class MapState extends UserRelatedState {
|
|||
];
|
||||
}
|
||||
console.warn("Locking the bounds to ", layout.lockLocation);
|
||||
this.leafletMap.addCallbackAndRunD(map => {
|
||||
// @ts-ignore
|
||||
map.setMaxBounds(layout.lockLocation);
|
||||
map.setMinZoom(layout.startZoom);
|
||||
})
|
||||
this.mainMapObject.installBounds(
|
||||
new BBox(layout.lockLocation),
|
||||
this.featureSwitchIsTesting.data
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,6 +377,24 @@ export default class MapState extends UserRelatedState {
|
|||
|
||||
flayers.push(flayer);
|
||||
}
|
||||
|
||||
for (const layer of layoutToUse.layers) {
|
||||
if(layer.filterIsSameAs === undefined){
|
||||
continue
|
||||
}
|
||||
const toReuse = flayers.find(l => l.layerDef.id === layer.filterIsSameAs)
|
||||
if(toReuse === undefined){
|
||||
throw "Error in layer "+layer.id+": it defines that it should be use the filters of "+layer.filterIsSameAs+", but this layer was not loaded"
|
||||
}
|
||||
console.warn("Linking filter and isDisplayed-states of "+layer.id+" and "+layer.filterIsSameAs)
|
||||
const selfLayer = flayers.findIndex(l => l.layerDef.id === layer.id)
|
||||
flayers[selfLayer] = {
|
||||
isDisplayed: toReuse.isDisplayed,
|
||||
layerDef: layer,
|
||||
appliedFilters: toReuse.appliedFilters
|
||||
};
|
||||
}
|
||||
|
||||
return new UIEventSource<FilteredLayer[]>(flayers);
|
||||
}
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ export interface LayerConfigJson {
|
|||
/**
|
||||
* All the extra questions for filtering
|
||||
*/
|
||||
filter?: (FilterConfigJson) [],
|
||||
filter?: (FilterConfigJson) [] | {sameAs: string},
|
||||
|
||||
/**
|
||||
* This block defines under what circumstances the delete dialog is shown for objects of this layer.
|
||||
|
|
|
@ -232,7 +232,7 @@ export interface LayoutConfigJson {
|
|||
|
||||
/**
|
||||
* If set to true, the basemap will not scroll outside of the area visible on initial zoom.
|
||||
* If set to [[lat0, lon0], [lat1, lon1]], the map will not scroll outside of those bounds.
|
||||
* If set to [[lon, lat], [lon, lat]], the map will not scroll outside of those bounds.
|
||||
* Off by default, which will enable panning to the entire world
|
||||
*/
|
||||
lockLocation?: boolean | [[number, number], [number, number]] | number[][];
|
||||
|
|
|
@ -24,6 +24,7 @@ import Link from "../../UI/Base/Link";
|
|||
import {Utils} from "../../Utils";
|
||||
import {TagsFilter} from "../../Logic/Tags/TagsFilter";
|
||||
import Table from "../../UI/Base/Table";
|
||||
import FilterConfigJson from "./Json/FilterConfigJson";
|
||||
|
||||
export default class LayerConfig extends WithContextLoader {
|
||||
|
||||
|
@ -58,7 +59,8 @@ export default class LayerConfig extends WithContextLoader {
|
|||
|
||||
public readonly tagRenderings: TagRenderingConfig[];
|
||||
public readonly filters: FilterConfig[];
|
||||
|
||||
public readonly filterIsSameAs: string;
|
||||
|
||||
constructor(
|
||||
json: LayerConfigJson,
|
||||
context?: string,
|
||||
|
@ -243,9 +245,14 @@ export default class LayerConfig extends WithContextLoader {
|
|||
|
||||
this.tagRenderings = (Utils.NoNull(json.tagRenderings) ?? []).map((tr, i) => new TagRenderingConfig(<TagRenderingConfigJson>tr, this.id + ".tagRenderings[" + i + "]"))
|
||||
|
||||
this.filters = (json.filter ?? []).map((option, i) => {
|
||||
return new FilterConfig(option, `${context}.filter-[${i}]`)
|
||||
});
|
||||
if(json.filter !== undefined && json.filter !== null && json.filter["sameAs"] !== undefined){
|
||||
this.filterIsSameAs = json.filter["sameAs"]
|
||||
this.filters = []
|
||||
}else{
|
||||
this.filters = (<FilterConfigJson[]>json.filter ?? []).map((option, i) => {
|
||||
return new FilterConfig(option, `${context}.filter-[${i}]`)
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
const duplicateIds = Utils.Dupiclates(this.filters.map(f => f.id))
|
||||
|
@ -302,8 +309,7 @@ export default class LayerConfig extends WithContextLoader {
|
|||
return undefined
|
||||
}
|
||||
const baseTags = TagUtils.changeAsProperties(this.source.osmTags.asChange({id: "node/-1"}))
|
||||
return mapRendering.GenerateLeafletStyle(new UIEventSource(baseTags), false,
|
||||
{noSize: true, includeBadges: false}).html
|
||||
return mapRendering.GetSimpleIcon(new UIEventSource(baseTags))
|
||||
}
|
||||
|
||||
public GenerateDocumentation(usedInThemes: string[], layerIsNeededBy: Map<string, string[]>, dependencies: {
|
||||
|
|
|
@ -66,7 +66,7 @@ export default class LayoutConfig {
|
|||
this.maintainer = json.maintainer;
|
||||
this.credits = json.credits;
|
||||
this.version = json.version;
|
||||
this.language = Array.from(Object.keys(json.title));
|
||||
this.language = json.mustHaveLanguage ?? Array.from(Object.keys(json.title));
|
||||
|
||||
{
|
||||
if (typeof json.title === "string") {
|
||||
|
|
|
@ -150,8 +150,8 @@ export default class PointRenderingConfig extends WithContextLoader {
|
|||
tags: UIEventSource<any>,
|
||||
clickable: boolean,
|
||||
options?: {
|
||||
noSize: false | boolean,
|
||||
includeBadges: true | boolean
|
||||
noSize?: false | boolean,
|
||||
includeBadges?: true | boolean
|
||||
}
|
||||
):
|
||||
{
|
||||
|
|
|
@ -53,14 +53,15 @@ export default class MinimapImplementation extends BaseUIElement implements Mini
|
|||
|
||||
public installBounds(factor: number | BBox, showRange?: boolean) {
|
||||
this.leafletMap.addCallbackD(leaflet => {
|
||||
let bounds;
|
||||
let bounds : {getEast(), getNorth(), getWest(), getSouth()};
|
||||
if (typeof factor === "number") {
|
||||
bounds = leaflet.getBounds().pad(factor)
|
||||
leaflet.setMaxBounds(bounds)
|
||||
const lbounds = leaflet.getBounds().pad(factor)
|
||||
leaflet.setMaxBounds(lbounds)
|
||||
bounds = lbounds;
|
||||
} else {
|
||||
// @ts-ignore
|
||||
leaflet.setMaxBounds(factor.toLeaflet())
|
||||
bounds = leaflet.getBounds()
|
||||
bounds = factor
|
||||
}
|
||||
|
||||
if (showRange) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import {UIEventSource} from "../../Logic/UIEventSource";
|
|||
import Hash from "../../Logic/Web/Hash";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import Img from "./Img";
|
||||
import Title from "./Title";
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -101,7 +102,8 @@ export default class ScrollableFullScreen extends UIElement {
|
|||
Hash.hash.setData(undefined)
|
||||
})
|
||||
|
||||
title.SetClass("block text-l sm:text-xl md:text-2xl w-full font-bold p-0 max-h-20vh overflow-y-auto self-center")
|
||||
title = new Title(title, 2)
|
||||
title.SetClass("text-l sm:text-xl md:text-2xl w-full p-0 max-h-20vh overflow-y-auto self-center")
|
||||
return new Combine([
|
||||
new Combine([
|
||||
new Combine([returnToTheMap, title])
|
||||
|
|
|
@ -21,7 +21,7 @@ export class SubtleButton extends UIElement {
|
|||
}
|
||||
|
||||
protected InnerRender(): string | BaseUIElement {
|
||||
const classes = "block flex p-3 my-2 bg-blue-100 rounded-lg hover:shadow-xl hover:bg-blue-200 link-no-underline";
|
||||
const classes = "block flex p-3 my-2 bg-subtle rounded-lg hover:shadow-xl hover:bg-unsubtle transition-colors transition-shadow link-no-underline";
|
||||
const message = Translations.W(this.message);
|
||||
let img;
|
||||
if ((this.imageUrl ?? "") === "") {
|
||||
|
|
|
@ -185,7 +185,7 @@ export default class CopyrightPanel extends Combine {
|
|||
...iconAttributions
|
||||
].map(e => e?.SetClass("mt-4")));
|
||||
this.SetClass("flex flex-col link-underline overflow-hidden")
|
||||
this.SetStyle("max-width: calc(100vw - 3em); width: 40rem; margin-left: 0.75rem; margin-right: 0.5rem")
|
||||
this.SetStyle("max-width:100%; width: 40rem; margin-left: 0.75rem; margin-right: 0.5rem")
|
||||
}
|
||||
|
||||
private static CodeContributors(): BaseUIElement {
|
||||
|
|
|
@ -115,17 +115,16 @@ export default class FilterView extends VariableUiElement {
|
|||
)
|
||||
|
||||
|
||||
const style =
|
||||
"display:flex;align-items:center;padding:0.5rem 0;";
|
||||
const layerIcon = layer.defaultIcon()?.SetClass("w-8 h-8 ml-2 shrink-0")
|
||||
const layerIconUnchecked = layer.defaultIcon()?.SetClass("opacity-50 w-8 h-8 ml-2")
|
||||
const toggleClasses = "layer-toggle flex flex-wrap items-center pt-2 pb-1 px-0";
|
||||
const layerIcon = layer.defaultIcon()?.SetClass("flex-shrink-0 w-8 h-8 ml-2")
|
||||
const layerIconUnchecked = layer.defaultIcon()?.SetClass("flex-shrink-0 opacity-50 w-8 h-8 ml-2")
|
||||
|
||||
const layerChecked = new Combine([icon, layerIcon, styledNameChecked, zoomStatus])
|
||||
.SetStyle(style)
|
||||
.SetClass(toggleClasses)
|
||||
.onClick(() => filteredLayer.isDisplayed.setData(false));
|
||||
|
||||
const layerNotChecked = new Combine([iconUnselected, layerIconUnchecked, styledNameUnChecked])
|
||||
.SetStyle(style)
|
||||
.SetClass(toggleClasses)
|
||||
.onClick(() => filteredLayer.isDisplayed.setData(true));
|
||||
|
||||
|
||||
|
@ -152,7 +151,7 @@ export default class FilterView extends VariableUiElement {
|
|||
|
||||
const [ui, actualTags] = FilterView.createFilter(filter)
|
||||
|
||||
ui.SetClass("mt-3")
|
||||
ui.SetClass("mt-1")
|
||||
toShow.push(ui)
|
||||
actualTags.addCallback(tagsToFilterFor => {
|
||||
flayer.appliedFilters.data.set(filter.id, tagsToFilterFor)
|
||||
|
@ -165,7 +164,7 @@ export default class FilterView extends VariableUiElement {
|
|||
}
|
||||
|
||||
return new Combine(toShow)
|
||||
.SetClass("flex flex-col p-2 ml-0 pl-12 bg-gray-200 pt-0 border-b-2 border-detail mb-4")
|
||||
.SetClass("flex flex-col p-2 ml-12 pl-1 pt-0 border-b-2 border-detail mb-4")
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -35,9 +35,7 @@ export default class LeftControls extends Combine {
|
|||
return defaultIcon;
|
||||
}
|
||||
const tags = {...feature.properties, button: "yes"}
|
||||
const elem = currentViewFL.layerDef.mapRendering[0]?.GenerateLeafletStyle(new UIEventSource(tags), false, {
|
||||
noSize: true
|
||||
})?.html
|
||||
const elem = currentViewFL.layerDef.mapRendering[0]?.GetSimpleIcon(new UIEventSource(tags));
|
||||
if (elem === undefined) {
|
||||
return defaultIcon
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ export class ImageUploadFlow extends Toggle {
|
|||
const label = new Combine([
|
||||
Svg.camera_plus_ui().SetClass("block w-12 h-12 p-1 text-4xl "),
|
||||
labelContent
|
||||
]).SetClass("p-2 border-4 border-black rounded-full font-bold h-full align-middle w-full flex justify-center")
|
||||
]).SetClass("p-2 border-4 border-detail rounded-full font-bold h-full align-middle w-full flex justify-center")
|
||||
|
||||
const fileSelector = new FileSelectorButton(label)
|
||||
fileSelector.GetValue().addCallback(filelist => {
|
||||
|
|
|
@ -62,7 +62,7 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
|
|||
layerConfig: LayerConfig,
|
||||
state: {}): BaseUIElement {
|
||||
const title = new TagRenderingAnswer(tags, layerConfig.title ?? new TagRenderingConfig("POI"), state)
|
||||
.SetClass("break-words font-bold sm:p-0.5 md:p-1 sm:p-1.5 md:p-2");
|
||||
.SetClass("break-words font-bold sm:p-0.5 md:p-1 sm:p-1.5 md:p-2 text-2xl");
|
||||
const titleIcons = new Combine(
|
||||
layerConfig.titleIcons.map(icon => new TagRenderingAnswer(tags, icon, state,
|
||||
"block w-8 h-8 max-h-8 align-baseline box-content sm:p-0.5 w-10",)
|
||||
|
|
|
@ -111,9 +111,8 @@ export default class TagRenderingQuestion extends Combine {
|
|||
|
||||
const saveButton = new Combine([
|
||||
options.saveButtonConstr(inputElement.GetValue()),
|
||||
new Toggle(Translations.t.general.testing.SetClass("alert"), undefined, state.featureSwitchIsTesting)
|
||||
])
|
||||
|
||||
|
||||
let bottomTags: BaseUIElement;
|
||||
if (options.bottomText !== undefined) {
|
||||
bottomTags = options.bottomText(inputElement.GetValue())
|
||||
|
@ -142,7 +141,9 @@ export default class TagRenderingQuestion extends Combine {
|
|||
inputElement,
|
||||
options.cancelButton,
|
||||
saveButton,
|
||||
bottomTags])
|
||||
bottomTags,
|
||||
new Toggle(Translations.t.general.testing.SetClass("alert"), undefined, state.featureSwitchIsTesting)
|
||||
])
|
||||
|
||||
|
||||
this.SetClass("question disable-links")
|
||||
|
|
|
@ -36,7 +36,7 @@ export class SubstitutedTranslation extends VariableUiElement {
|
|||
|
||||
super(
|
||||
Locale.language.map(language => {
|
||||
let txt = translation.textFor(language);
|
||||
let txt = translation?.textFor(language);
|
||||
if (txt === undefined) {
|
||||
return undefined
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ export class Translation extends BaseUIElement {
|
|||
|
||||
get txt(): string {
|
||||
return this.textFor(Translation.forcedLanguage ?? Locale.language.data)
|
||||
}
|
||||
}
|
||||
|
||||
static ExtractAllTranslationsFrom(object: any, context = ""): { context: string, tr: Translation }[] {
|
||||
const allTranslations: { context: string, tr: Translation }[] = []
|
||||
|
|
6
Utils.ts
6
Utils.ts
|
@ -305,6 +305,12 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
|||
if (!source.hasOwnProperty(key)) {
|
||||
continue
|
||||
}
|
||||
if (key.startsWith("=")) {
|
||||
const trimmedKey = key.substr(1);
|
||||
target[trimmedKey] = source[key]
|
||||
continue
|
||||
}
|
||||
|
||||
if (key.startsWith("+") || key.endsWith("+")) {
|
||||
const trimmedKey = key.replace("+", "");
|
||||
const sourceV = source[key];
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"mapRendering": [
|
||||
{
|
||||
"icon": "crosshair:#00f",
|
||||
"icon": "crosshair:var(--catch-detail-color)",
|
||||
"iconSize": "40,40,center",
|
||||
"location": [
|
||||
"point",
|
||||
|
|
|
@ -151,8 +151,9 @@
|
|||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "<img src=\"./assets/layers/nature_reserve/Natuurpunt.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door Natuurpunt"
|
||||
}
|
||||
"nl": "Dit gebied wordt beheerd door Natuurpunt"
|
||||
},
|
||||
"icon": "./assets/layers/nature_reserve/Natuurpunt.jpg"
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
|
@ -161,8 +162,9 @@
|
|||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "<img src=\"./assets/layers/nature_reserve/Natuurpunt.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door {operator}"
|
||||
"nl": "Dit gebied wordt beheerd door {operator}"
|
||||
},
|
||||
"icon": "./assets/layers/nature_reserve/Natuurpunt.jpg",
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
|
@ -172,8 +174,9 @@
|
|||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "<img src=\"./assets/layers/nature_reserve/ANB.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door het Agentschap Natuur en Bos"
|
||||
}
|
||||
"nl": "Dit gebied wordt beheerd door het Agentschap Natuur en Bos"
|
||||
},
|
||||
"icon": "./assets/layers/nature_reserve/ANB.jpg"
|
||||
}
|
||||
],
|
||||
"id": "Operator tag"
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
:root {
|
||||
--subtle-detail-color: #007759;
|
||||
--subtle-detail-color-contrast: #ffffff;
|
||||
--subtle-detail-color-light-contrast: lightgrey;
|
||||
--subtle-detail-color-light-contrast: white;
|
||||
|
||||
--catch-detail-color: #0fff00;
|
||||
--unsubtle-detail-color: #b34f26;
|
||||
--unsubtle-detail-color-contrast: #ffffff;
|
||||
--catch-detail-color: #FE6F32;
|
||||
--catch-detail-color-contrast: #ffffff;
|
||||
--alert-color: #fee4d1;
|
||||
--background-color: white;
|
||||
|
@ -31,7 +33,21 @@ body {
|
|||
font-family: 'Open Sans Regular', sans-serif;
|
||||
}
|
||||
|
||||
h1 h2 h3 h4 {
|
||||
.layer-toggle .alert {
|
||||
background: unset !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.layer-toggle svg path {
|
||||
fill: var(--foreground-color) !important;
|
||||
}
|
||||
|
||||
.layer-toggle .alert::before {
|
||||
content: " - "
|
||||
}
|
||||
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-family: 'Amaranth', sans-serif;
|
||||
}
|
||||
|
||||
|
@ -43,4 +59,4 @@ h1 h2 h3 h4 {
|
|||
.tab-non-active svg path {
|
||||
fill: white !important;
|
||||
stroke: white !important;
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@
|
|||
"startLat": 51.20875,
|
||||
"startLon": 3.22435,
|
||||
"startZoom": 15,
|
||||
"lockLocation": [[2.1,50.40],[ 6.4,51.54]],
|
||||
"widenFactor": 2,
|
||||
"socialImage": "",
|
||||
"defaultBackgroundId": "CartoDB.Positron",
|
||||
|
@ -64,7 +65,10 @@
|
|||
"render": "circle:#FE6F32;./assets/themes/natuurpunt/nature_reserve.svg"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"=filter": {
|
||||
"sameAs": "nature_reserve_centerpoints"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -183,7 +187,12 @@
|
|||
"source": {
|
||||
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/natuurpunt_cache/natuurpunt_{layer}_{z}_{x}_{y}.geojson",
|
||||
"geoJsonZoomLevel": 12,
|
||||
"isOsmCache": true
|
||||
"isOsmCache": true,
|
||||
"osmTags": {
|
||||
"+and": [
|
||||
"operator~.*[nN]atuurpunt.*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"mapRendering": [
|
||||
{
|
||||
|
@ -313,7 +322,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"builtin": "gps_location_history",
|
||||
"builtin": "gps_track",
|
||||
"override": {
|
||||
"name": null
|
||||
}
|
||||
|
|
|
@ -896,12 +896,12 @@ video {
|
|||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.mt-3 {
|
||||
margin-top: 0.75rem;
|
||||
.ml-12 {
|
||||
margin-left: 3rem;
|
||||
}
|
||||
|
||||
.ml-0 {
|
||||
margin-left: 0px;
|
||||
.mt-3 {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.mb-10 {
|
||||
|
@ -1437,11 +1437,6 @@ video {
|
|||
background-color: rgba(255, 255, 255, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-blue-100 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(219, 234, 254, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gray-400 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(156, 163, 175, var(--tw-bg-opacity));
|
||||
|
@ -1452,16 +1447,16 @@ video {
|
|||
background-color: rgba(224, 231, 255, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gray-200 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(229, 231, 235, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-black {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(0, 0, 0, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gray-200 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(229, 231, 235, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gray-100 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(243, 244, 246, var(--tw-bg-opacity));
|
||||
|
@ -1514,6 +1509,11 @@ video {
|
|||
padding: 2rem;
|
||||
}
|
||||
|
||||
.px-0 {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.pb-12 {
|
||||
padding-bottom: 3rem;
|
||||
}
|
||||
|
@ -1546,8 +1546,8 @@ video {
|
|||
padding-right: 0.25rem;
|
||||
}
|
||||
|
||||
.pl-12 {
|
||||
padding-left: 3rem;
|
||||
.pt-2 {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
.pt-0 {
|
||||
|
@ -1590,10 +1590,6 @@ video {
|
|||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.pt-2 {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -1783,6 +1779,12 @@ video {
|
|||
transition-duration: 150ms;
|
||||
}
|
||||
|
||||
.transition-shadow {
|
||||
transition-property: box-shadow;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
|
||||
.transition-opacity {
|
||||
transition-property: opacity;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
@ -1805,101 +1807,17 @@ video {
|
|||
z-index: 10001
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
border-width: 1px;
|
||||
border-color: transparent;
|
||||
--tw-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
border-radius: 1.5rem;
|
||||
--tw-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgba(191, 219, 254, var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgba(147, 197, 253, var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-top: 0.25rem;
|
||||
margin-right: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
font-weight: 500;
|
||||
--tw-text-opacity: 1;
|
||||
color: rgba(255, 255, 255, var(--tw-text-opacity));
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(37, 99, 235, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(29, 78, 216, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.btn:focus {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgba(29, 78, 216, var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(75, 85, 99, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(55, 65, 81, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.btn-disabled {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(107, 114, 128, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.btn-disabled:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(107, 114, 128, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.btn-disabled {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgba(209, 213, 219, var(--tw-text-opacity));
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgba(229, 231, 235, var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.btn-disabled:hover {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgba(229, 231, 235, var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.btn-disabled:focus {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgba(229, 231, 235, var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.btn-disabled {
|
||||
cursor: default;
|
||||
.bg-subtle {
|
||||
background-color: var(--subtle-detail-color);
|
||||
color: var(--subtle-detail-color-contrast);
|
||||
}
|
||||
|
||||
:root {
|
||||
--subtle-detail-color: #e5f5ff;
|
||||
--subtle-detail-color: #DBEAFE;
|
||||
--subtle-detail-color-contrast: black;
|
||||
--subtle-detail-color-light-contrast: lightgrey;
|
||||
--unsubtle-detail-color: #BFDBFE;
|
||||
--unsubtle-detail-color-contrast: black;
|
||||
--catch-detail-color: #3a3aeb;
|
||||
--catch-detail-color-contrast: white;
|
||||
--alert-color: #fee4d1;
|
||||
|
@ -1967,16 +1885,45 @@ a {
|
|||
color: var(--foreground-color);
|
||||
}
|
||||
|
||||
btn {
|
||||
margin-top: 0.25rem;
|
||||
margin-right: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
.btn {
|
||||
margin-top: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
line-height: 1.25rem;
|
||||
font-weight: 500;
|
||||
--tw-text-opacity: 1;
|
||||
color: var(--catch-detail-color-contrast);
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: var(--catch-detail-color);
|
||||
display: inline-flex;
|
||||
border-radius: 1.5rem;
|
||||
padding-top: 0.75rem;
|
||||
padding-bottom: 0.75rem;
|
||||
padding-left: 1.25rem;
|
||||
padding-right: 1.25rem;
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
/*-- invisible border: rendered on hover*/
|
||||
border: 3px solid var(--unsubtle-detail-color);
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
border: 3px solid var(--catch-detail-color);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: var(--unsubtle-detail-color);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: var(--catch-detail-color);
|
||||
}
|
||||
|
||||
.btn-disabled {
|
||||
filter: saturate(0.3);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.btn-disabled:hover {
|
||||
border: 3px solid var(--unsubtle-detail-color);
|
||||
}
|
||||
|
||||
.h-min {
|
||||
|
@ -2000,9 +1947,8 @@ btn {
|
|||
}
|
||||
|
||||
.link-underline a {
|
||||
-webkit-text-decoration: underline 1px #0078a855;
|
||||
text-decoration: underline 1px #0078a855;
|
||||
color: #0078A8;
|
||||
-webkit-text-decoration: underline 1px var(--foreground-color);
|
||||
text-decoration: underline 1px var(--foreground-color);
|
||||
}
|
||||
|
||||
.link-no-underline a {
|
||||
|
@ -2083,6 +2029,7 @@ li::marker {
|
|||
}
|
||||
|
||||
.leaflet-container {
|
||||
font: unset !important;
|
||||
background-color: var(--background-color) !important;
|
||||
}
|
||||
|
||||
|
@ -2134,6 +2081,7 @@ li::marker {
|
|||
|
||||
.alert {
|
||||
background-color: var(--alert-color);
|
||||
color: var(--foreground-color);
|
||||
font-weight: bold;
|
||||
border-radius: 1em;
|
||||
margin: 0.25em;
|
||||
|
@ -2326,6 +2274,10 @@ li::marker {
|
|||
|
||||
/***************** Info box (box containing features and questions ******************/
|
||||
|
||||
input {
|
||||
color: var(--foreground-color)
|
||||
}
|
||||
|
||||
.leaflet-popup-content {
|
||||
width: 45em !important;
|
||||
margin: 0.25rem !important;
|
||||
|
@ -2383,11 +2335,6 @@ li::marker {
|
|||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
.hover\:bg-blue-200:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(191, 219, 254, var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-indigo-200:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(199, 210, 254, var(--tw-bg-opacity));
|
||||
|
@ -2407,6 +2354,11 @@ li::marker {
|
|||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.hover\:bg-unsubtle:hover {
|
||||
background-color: var(--unsubtle-detail-color);
|
||||
color: var(--unsubtle-detail-color-contrast);
|
||||
}
|
||||
|
||||
.group:hover .group-hover\:text-blue-800 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgba(30, 64, 175, var(--tw-text-opacity));
|
||||
|
|
89
index.css
89
index.css
|
@ -24,38 +24,33 @@
|
|||
.w-160 {
|
||||
width: 40rem;
|
||||
}
|
||||
|
||||
.bg-subtle {
|
||||
background-color: var(--subtle-detail-color);
|
||||
color: var(--subtle-detail-color-contrast);
|
||||
}
|
||||
|
||||
.bg-unsubtle {
|
||||
background-color: var(--unsubtle-detail-color);
|
||||
color: var(--unsubtle-detail-color-contrast);
|
||||
}
|
||||
|
||||
.bg-catch {
|
||||
background-color: var(--catch-detail-color);
|
||||
color: var(--catch-detail-color-contrast);
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
@apply inline-flex justify-center;
|
||||
@apply py-2 px-4;
|
||||
@apply border border-transparent shadow-sm;
|
||||
@apply shadow-sm rounded-3xl;
|
||||
@apply ring-2 ring-blue-200 hover:ring-blue-300;
|
||||
@apply mt-1 mr-1;
|
||||
@apply text-sm font-medium text-white;
|
||||
@apply bg-blue-600 hover:bg-blue-700;
|
||||
@apply focus:outline-none focus:ring-blue-700;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
@apply bg-gray-600 hover:bg-gray-700;
|
||||
}
|
||||
|
||||
.btn-disabled {
|
||||
@apply bg-gray-500 hover:bg-gray-500;
|
||||
@apply text-gray-300;
|
||||
@apply ring-gray-200 hover:ring-gray-200 focus:ring-gray-200;
|
||||
@apply cursor-default;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
:root {
|
||||
--subtle-detail-color: #e5f5ff;
|
||||
--subtle-detail-color: #DBEAFE;
|
||||
--subtle-detail-color-contrast: black;
|
||||
--subtle-detail-color-light-contrast: lightgrey;
|
||||
|
||||
--unsubtle-detail-color: #BFDBFE;
|
||||
--unsubtle-detail-color-contrast: black;
|
||||
--catch-detail-color: #3a3aeb;
|
||||
--catch-detail-color-contrast: white;
|
||||
--alert-color: #fee4d1;
|
||||
|
@ -123,16 +118,45 @@ a {
|
|||
color: var(--foreground-color);
|
||||
}
|
||||
|
||||
btn {
|
||||
margin-top: 0.25rem;
|
||||
margin-right: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
.btn {
|
||||
margin-top: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
line-height: 1.25rem;
|
||||
font-weight: 500;
|
||||
--tw-text-opacity: 1;
|
||||
color: var(--catch-detail-color-contrast);
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: var(--catch-detail-color);
|
||||
display: inline-flex;
|
||||
border-radius: 1.5rem;
|
||||
padding-top: 0.75rem;
|
||||
padding-bottom: 0.75rem;
|
||||
padding-left: 1.25rem;
|
||||
padding-right: 1.25rem;
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
/*-- invisible border: rendered on hover*/
|
||||
border: 3px solid var(--unsubtle-detail-color);
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
border: 3px solid var(--catch-detail-color);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: var(--unsubtle-detail-color);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: var(--catch-detail-color);
|
||||
}
|
||||
|
||||
.btn-disabled {
|
||||
filter: saturate(0.3);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.btn-disabled:hover {
|
||||
border: 3px solid var(--unsubtle-detail-color);
|
||||
}
|
||||
|
||||
.h-min {
|
||||
|
@ -153,8 +177,7 @@ btn {
|
|||
}
|
||||
|
||||
.link-underline a {
|
||||
text-decoration: underline 1px #0078a855;;
|
||||
color: #0078A8;
|
||||
text-decoration: underline 1px var(--foreground-color);
|
||||
}
|
||||
|
||||
.link-no-underline a {
|
||||
|
@ -239,6 +262,7 @@ li::marker {
|
|||
}
|
||||
|
||||
.leaflet-container {
|
||||
font: unset !important;
|
||||
background-color: var(--background-color) !important;
|
||||
}
|
||||
|
||||
|
@ -292,6 +316,7 @@ li::marker {
|
|||
|
||||
.alert {
|
||||
background-color: var(--alert-color);
|
||||
color: var(--foreground-color);
|
||||
font-weight: bold;
|
||||
border-radius: 1em;
|
||||
margin: 0.25em;
|
||||
|
@ -434,6 +459,9 @@ li::marker {
|
|||
|
||||
/***************** Info box (box containing features and questions ******************/
|
||||
|
||||
input {
|
||||
color: var(--foreground-color)
|
||||
}
|
||||
|
||||
.leaflet-popup-content {
|
||||
width: 45em !important;
|
||||
|
@ -489,6 +517,7 @@ li::marker {
|
|||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
|
||||
.zebra-table tr:nth-child(even) {
|
||||
background-color: #f2f2f2;
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
"name": "index",
|
||||
"short_name": "MapComplete",
|
||||
"start_url": "index.html",
|
||||
"lang": "en",
|
||||
"display": "standalone",
|
||||
"background_color": "#fff",
|
||||
"description": "A thematic map viewer and editor based on OpenStreetMap",
|
||||
|
|
|
@ -3240,13 +3240,13 @@
|
|||
"Operator tag": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "<img src=\"./assets/layers/nature_reserve/Natuurpunt.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door Natuurpunt"
|
||||
"then": "Dit gebied wordt beheerd door Natuurpunt"
|
||||
},
|
||||
"1": {
|
||||
"then": "<img src=\"./assets/layers/nature_reserve/Natuurpunt.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door {operator}"
|
||||
"then": "Dit gebied wordt beheerd door {operator}"
|
||||
},
|
||||
"2": {
|
||||
"then": "<img src=\"./assets/layers/nature_reserve/ANB.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door het Agentschap Natuur en Bos"
|
||||
"then": "Dit gebied wordt beheerd door het Agentschap Natuur en Bos"
|
||||
}
|
||||
},
|
||||
"question": "Wie beheert dit gebied?",
|
||||
|
|
|
@ -7,12 +7,9 @@
|
|||
"homepage": "https://mapcomplete.osm.be",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"increase-memory": "export NODE_OPTIONS=--max_old_space_size=8364",
|
||||
"start": "npm run start:prepare && npm-run-all --parallel start:parallel:*",
|
||||
"strt": "npm run start:prepare && npm run start:parallel:parcel",
|
||||
"start:prepare": "ts-node scripts/generateLayerOverview.ts --no-fail && npm run increase-memory",
|
||||
"start:parallel:parcel": "parcel serve *.html UI/** Logic/** assets/*.json assets/svg/* assets/generated/* assets/layers/*/*.svg assets/layers/*/*.jpg assets/layers/*/*.png assets/layers/*/*.css assets/tagRenderings/*.json assets/themes/*/*.svg assets/themes/*/*.ttf assets/themes/*/*/*.ttf aassets/themes/*/*.otf assets/themes/*/*/*.otf ssets/themes/*/*.css assets/themes/*/*.jpg assets/themes/*/*.png vendor/* vendor/*/*",
|
||||
"start:parallel:tailwindcli": "tailwindcss -i index.css -o css/index-tailwind-output.css --watch",
|
||||
"start": "npm run generate:layeroverview && npm run ",
|
||||
"strt": "export NODE_OPTIONS=--max_old_space_size=8364 && parcel serve *.html UI/** Logic/** assets/*.json assets/svg/* assets/generated/* assets/layers/*/*.svg assets/layers/*/*.jpg assets/layers/*/*.png assets/layers/*/*.css assets/tagRenderings/*.json assets/themes/*/*.svg assets/themes/*/*.ttf assets/themes/*/*/*.ttf aassets/themes/*/*.otf assets/themes/*/*/*.otf ssets/themes/*/*.css assets/themes/*/*.jpg assets/themes/*/*.png vendor/* vendor/*/*",
|
||||
"watch:css": "tailwindcss -i index.css -o css/index-tailwind-output.css --watch",
|
||||
"generate:css": "tailwindcss -i index.css -o css/index-tailwind-output.css",
|
||||
"test": "ts-node test/TestAll.ts",
|
||||
"init": "npm ci && npm run generate && npm run generate:editor-layer-index && npm run generate:layouts && npm run clean",
|
||||
|
|
|
@ -195,8 +195,16 @@ if (!existsSync(generatedDir)) {
|
|||
const blacklist = ["", "test", ".", "..", "manifest", "index", "land", "preferences", "account", "openstreetmap", "custom", "theme"]
|
||||
// @ts-ignore
|
||||
const all: LayoutConfigJson[] = all_known_layouts.themes;
|
||||
const args = process.argv
|
||||
const theme = args[2]
|
||||
if(theme !== undefined){
|
||||
console.warn("Only generating layout "+theme)
|
||||
}
|
||||
for (const i in all) {
|
||||
const layoutConfigJson: LayoutConfigJson = all[i]
|
||||
if(theme !== undefined && layoutConfigJson.id !== theme){
|
||||
continue
|
||||
}
|
||||
const layout = new LayoutConfig(layoutConfigJson, true, "generating layouts")
|
||||
const layoutName = layout.id
|
||||
if (blacklist.indexOf(layoutName.toLowerCase()) >= 0) {
|
||||
|
|
Loading…
Reference in a new issue