mirror of
https://github.com/umap-project/umap.git
synced 2025-05-07 15:01:48 +02:00
Compare commits
3 commits
0b818e8b75
...
ba3a1ccd33
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ba3a1ccd33 | ||
![]() |
88ee836b34 | ||
![]() |
4d1286e0ef |
29 changed files with 85 additions and 312 deletions
|
@ -47,7 +47,7 @@ Voici un bref passage en revu des différents imports proposés et pour finir l
|
||||||
|
|
||||||
## 1. Importer le contour d’une commune
|
## 1. Importer le contour d’une commune
|
||||||
|
|
||||||
Cliquez sur l’outil d’importation en bas de la barre de droite, puis cliquez sur le lien « Assistants d’import ».
|
Cliquez sur l’outil d’importation en bas de la barre de droite, puis descendez jusqu’au cadre « Assistants d’import ».
|
||||||
|
|
||||||
Cliquez sur « Communes France » et sélectionnez la commune souhaitée dans une liste déroulante. Une fois la commune sélectionnée, le format est reconnu automatiquement (geojson) puis le type de calque (cliquer sur « ? » pour savoir quel choix opérer)
|
Cliquez sur « Communes France » et sélectionnez la commune souhaitée dans une liste déroulante. Une fois la commune sélectionnée, le format est reconnu automatiquement (geojson) puis le type de calque (cliquer sur « ? » pour savoir quel choix opérer)
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ Une fois cet import réalisé, tout est réglable : couleur de contour, de fond,
|
||||||
|
|
||||||
## 2. Importer les contours des départements ou des régions
|
## 2. Importer les contours des départements ou des régions
|
||||||
|
|
||||||
Cliquez sur l’outil d’importation en bas de la barre de droite, puis cliquez sur le lien « Assistants d’import ».
|
Cliquez sur l’outil d’importation en bas de la barre de droite, puis descendez jusqu’au cadre « Assistants d’import ».
|
||||||
|
|
||||||
Cliquez sur « Contours nationaux » puis soit départements, soit régions et enfin le type de calque (voir supra l’explication). Tous les départements sont importés :
|
Cliquez sur « Contours nationaux » puis soit départements, soit régions et enfin le type de calque (voir supra l’explication). Tous les départements sont importés :
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ Cliquez sur « Contours nationaux » puis soit départements, soit régions et
|
||||||
|
|
||||||
## 3. Importer un point d’intérêt issu de GeoDataMine
|
## 3. Importer un point d’intérêt issu de GeoDataMine
|
||||||
|
|
||||||
Cliquez sur l’outil d’importation en bas de la barre de droite, puis cliquez sur le lien « Assistants d’import ».
|
Cliquez sur l’outil d’importation en bas de la barre de droite, puis descendez jusqu’au cadre « Assistants d’import ».
|
||||||
|
|
||||||
Cliquez sur « GeoDataMine (thèmes OSM) » et sélectionnez les informations souhaitées, routes, bâtiments, commerces, services publics, …
|
Cliquez sur « GeoDataMine (thèmes OSM) » et sélectionnez les informations souhaitées, routes, bâtiments, commerces, services publics, …
|
||||||
Par exemple, en sélectionnant les points d’eau potable de la CA du Grand Avignon, puis « Copier dans un calque »
|
Par exemple, en sélectionnant les points d’eau potable de la CA du Grand Avignon, puis « Copier dans un calque »
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Force rtfd to use a recent version of mkdocs
|
# Force rtfd to use a recent version of mkdocs
|
||||||
mkdocs==1.6.1
|
mkdocs==1.6.1
|
||||||
pymdown-extensions==10.12
|
pymdown-extensions==10.12
|
||||||
mkdocs-material==9.5.47
|
mkdocs-material==9.5.44
|
||||||
mkdocs-static-i18n==1.2.3
|
mkdocs-static-i18n==1.2.3
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 734 KiB After Width: | Height: | Size: 3.4 MiB |
|
@ -175,6 +175,11 @@ UMAP_EXTRA_URLS = {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### UMAP_KEEP_VERSIONS
|
||||||
|
|
||||||
|
How many datalayer versions to keep. 10 by default.
|
||||||
|
|
||||||
|
|
||||||
#### UMAP_DEFAULT_EDIT_STATUS
|
#### UMAP_DEFAULT_EDIT_STATUS
|
||||||
|
|
||||||
Define the map default edit status.
|
Define the map default edit status.
|
||||||
|
@ -265,16 +270,6 @@ Available importers:
|
||||||
- `communesfr`: download French communes boundaries, from https://geo.api.gouv.fr/
|
- `communesfr`: download French communes boundaries, from https://geo.api.gouv.fr/
|
||||||
- `datasets`: define URLs you want to promote to users, with a `name` and a `format`
|
- `datasets`: define URLs you want to promote to users, with a `name` and a `format`
|
||||||
|
|
||||||
#### UMAP_KEEP_VERSIONS
|
|
||||||
|
|
||||||
How many datalayer versions to keep. 10 by default.
|
|
||||||
|
|
||||||
#### UMAP_LABEL_KEYS
|
|
||||||
|
|
||||||
List of properties to consider as "Feature label" (to show in popup or in browser).
|
|
||||||
|
|
||||||
UMAP_LABEL_KEYS = ["name", "title"]
|
|
||||||
|
|
||||||
#### UMAP_MAPS_PER_PAGE
|
#### UMAP_MAPS_PER_PAGE
|
||||||
|
|
||||||
How many maps to show in maps list, like search or home page.
|
How many maps to show in maps list, like search or home page.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Force rtfd to use a recent version of mkdocs
|
# Force rtfd to use a recent version of mkdocs
|
||||||
mkdocs==1.6.1
|
mkdocs==1.6.1
|
||||||
pymdown-extensions==10.12
|
pymdown-extensions==10.12
|
||||||
mkdocs-material==9.5.47
|
mkdocs-material==9.5.44
|
||||||
mkdocs-static-i18n==1.2.3
|
mkdocs-static-i18n==1.2.3
|
||||||
|
|
|
@ -44,10 +44,10 @@ dependencies = [
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
dev = [
|
dev = [
|
||||||
"hatch==1.13.0",
|
"hatch==1.13.0",
|
||||||
"ruff==0.8.1",
|
"ruff==0.7.4",
|
||||||
"djlint==1.36.3",
|
"djlint==1.36.1",
|
||||||
"mkdocs==1.6.1",
|
"mkdocs==1.6.1",
|
||||||
"mkdocs-material==9.5.47",
|
"mkdocs-material==9.5.44",
|
||||||
"mkdocs-static-i18n==1.2.3",
|
"mkdocs-static-i18n==1.2.3",
|
||||||
"vermin==1.6.0",
|
"vermin==1.6.0",
|
||||||
"pymdown-extensions==10.12",
|
"pymdown-extensions==10.12",
|
||||||
|
@ -56,10 +56,10 @@ dev = [
|
||||||
test = [
|
test = [
|
||||||
"factory-boy==3.3.1",
|
"factory-boy==3.3.1",
|
||||||
"playwright>=1.39",
|
"playwright>=1.39",
|
||||||
"pytest==8.3.4",
|
"pytest==8.3.3",
|
||||||
"pytest-django==4.9.0",
|
"pytest-django==4.9.0",
|
||||||
"pytest-playwright==0.6.2",
|
"pytest-playwright==0.5.2",
|
||||||
"pytest-rerunfailures==15.0",
|
"pytest-rerunfailures==14.0",
|
||||||
"pytest-xdist>=3.5.0,<4",
|
"pytest-xdist>=3.5.0,<4",
|
||||||
]
|
]
|
||||||
docker = [
|
docker = [
|
||||||
|
@ -68,7 +68,7 @@ docker = [
|
||||||
sync = [
|
sync = [
|
||||||
"channels==4.2.0",
|
"channels==4.2.0",
|
||||||
"daphne==4.1.2",
|
"daphne==4.1.2",
|
||||||
"pydantic==2.10.2",
|
"pydantic==2.9.2",
|
||||||
"websockets==13.1",
|
"websockets==13.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -273,7 +273,6 @@ UMAP_HOME_FEED = "latest"
|
||||||
UMAP_IMPORTERS = {}
|
UMAP_IMPORTERS = {}
|
||||||
UMAP_HOST_INFOS = {}
|
UMAP_HOST_INFOS = {}
|
||||||
UMAP_PURGATORY_ROOT = "/tmp/umappurgatory"
|
UMAP_PURGATORY_ROOT = "/tmp/umappurgatory"
|
||||||
UMAP_LABEL_KEYS = ["name", "title"]
|
|
||||||
|
|
||||||
UMAP_READONLY = env("UMAP_READONLY", default=False)
|
UMAP_READONLY = env("UMAP_READONLY", default=False)
|
||||||
UMAP_GZIP = True
|
UMAP_GZIP = True
|
||||||
|
|
|
@ -65,9 +65,7 @@ body.login header {
|
||||||
.login-grid .login-openstreetmap-oauth2 {
|
.login-grid .login-openstreetmap-oauth2 {
|
||||||
background-image: url("./openstreetmap.png");
|
background-image: url("./openstreetmap.png");
|
||||||
}
|
}
|
||||||
.login-grid .login-keycloak {
|
|
||||||
background-image: url("./keycloak.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* **************************** */
|
/* **************************** */
|
||||||
/* home */
|
/* home */
|
||||||
|
|
|
@ -78,7 +78,8 @@ input[type="submit"] {
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 7px 14px;
|
padding: 7px;
|
||||||
|
width: 100%;
|
||||||
min-height: 32px;
|
min-height: 32px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -91,12 +92,6 @@ input[type="submit"] {
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
border: 1px solid #1b1f20;
|
border: 1px solid #1b1f20;
|
||||||
}
|
}
|
||||||
.dark .button.primary:not([disabled]),
|
|
||||||
.dark [type="button"].primary:not([disabled]) {
|
|
||||||
background-color: var(--color-brightCyan);
|
|
||||||
color: var(--color-dark);
|
|
||||||
border: 1px solid #1b1f20;
|
|
||||||
}
|
|
||||||
.dark .button:hover,
|
.dark .button:hover,
|
||||||
.dark [type="button"]:hover,
|
.dark [type="button"]:hover,
|
||||||
.dark input[type="submit"]:hover {
|
.dark input[type="submit"]:hover {
|
||||||
|
@ -105,11 +100,6 @@ input[type="submit"] {
|
||||||
.dark a {
|
.dark a {
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
}
|
}
|
||||||
.dark [type="button"][disabled],
|
|
||||||
.dark input[type="submit"][disabled] {
|
|
||||||
background-color: var(--color-mediumGray);
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
button.flat,
|
button.flat,
|
||||||
[type="button"].flat,
|
[type="button"].flat,
|
||||||
.dark [type="button"].flat {
|
.dark [type="button"].flat {
|
||||||
|
|
|
@ -165,9 +165,7 @@ class Feature {
|
||||||
}
|
}
|
||||||
|
|
||||||
getSlug() {
|
getSlug() {
|
||||||
return (
|
return this.properties[this._umap.getProperty('slugKey') || 'name'] || ''
|
||||||
this.properties[this._umap.getProperty('slugKey') || U.DEFAULT_LABEL_KEY] || ''
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getPermalink() {
|
getPermalink() {
|
||||||
|
@ -236,23 +234,15 @@ class Feature {
|
||||||
container.appendChild(builder.build())
|
container.appendChild(builder.build())
|
||||||
|
|
||||||
const properties = []
|
const properties = []
|
||||||
let labelKeyFound = undefined
|
|
||||||
for (const property of this.datalayer._propertiesIndex) {
|
for (const property of this.datalayer._propertiesIndex) {
|
||||||
if (!labelKeyFound && U.LABEL_KEYS.includes(property)) {
|
if (['name', 'description'].includes(property)) {
|
||||||
labelKeyFound = property
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (property === 'description') {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
properties.push([`properties.${property}`, { label: property }])
|
properties.push([`properties.${property}`, { label: property }])
|
||||||
}
|
}
|
||||||
// We always want name and description for now (properties management to come)
|
// We always want name and description for now (properties management to come)
|
||||||
properties.unshift('properties.description')
|
properties.unshift('properties.description')
|
||||||
if (!labelKeyFound) {
|
properties.unshift('properties.name')
|
||||||
labelKeyFound = U.DEFAULT_LABEL_KEY
|
|
||||||
}
|
|
||||||
properties.unshift([`properties.${labelKeyFound}`, { label: labelKeyFound }])
|
|
||||||
builder = new U.FormBuilder(this, properties, {
|
builder = new U.FormBuilder(this, properties, {
|
||||||
id: 'umap-feature-properties',
|
id: 'umap-feature-properties',
|
||||||
})
|
})
|
||||||
|
@ -265,7 +255,7 @@ class Feature {
|
||||||
this.getAdvancedEditActions(advancedActions)
|
this.getAdvancedEditActions(advancedActions)
|
||||||
const onLoad = this._umap.editPanel.open({ content: container })
|
const onLoad = this._umap.editPanel.open({ content: container })
|
||||||
onLoad.then(() => {
|
onLoad.then(() => {
|
||||||
builder.helpers[`properties.${labelKeyFound}`].input.focus()
|
builder.helpers['properties.name'].input.focus()
|
||||||
})
|
})
|
||||||
this._umap.editedFeature = this
|
this._umap.editedFeature = this
|
||||||
if (!this.ui.isOnScreen(this._umap._leafletMap.getBounds())) this.zoomTo(event)
|
if (!this.ui.isOnScreen(this._umap._leafletMap.getBounds())) this.zoomTo(event)
|
||||||
|
@ -326,21 +316,19 @@ class Feature {
|
||||||
|
|
||||||
endEdit() {}
|
endEdit() {}
|
||||||
|
|
||||||
getDisplayName() {
|
getDisplayName(fallback) {
|
||||||
const keys = U.LABEL_KEYS.slice() // Copy.
|
const key = this.getOption('labelKey') || 'name'
|
||||||
const labelKey = this.getOption('labelKey')
|
|
||||||
// Variables mode.
|
// Variables mode.
|
||||||
if (labelKey) {
|
if (Utils.hasVar(key)) {
|
||||||
if (Utils.hasVar(labelKey)) {
|
return Utils.greedyTemplate(key, this.extendedProperties())
|
||||||
return Utils.greedyTemplate(labelKey, this.extendedProperties())
|
|
||||||
}
|
}
|
||||||
keys.unshift(labelKey)
|
// Simple mode.
|
||||||
}
|
return (
|
||||||
for (const key of keys) {
|
this.properties[key] ||
|
||||||
const value = this.properties[key]
|
this.properties.title ||
|
||||||
if (value) return value
|
fallback ||
|
||||||
}
|
this.datalayer.getName()
|
||||||
return this.datalayer.getName()
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
hasPopupFooter() {
|
hasPopupFooter() {
|
||||||
|
|
|
@ -289,7 +289,7 @@ export class DataLayer extends ServerStored {
|
||||||
|
|
||||||
reindex() {
|
reindex() {
|
||||||
const features = Object.values(this._features)
|
const features = Object.values(this._features)
|
||||||
this.sortFeatures(features)
|
Utils.sortFeatures(features, this._umap.getProperty('sortKey'), U.lang)
|
||||||
this._index = features.map((feature) => stamp(feature))
|
this._index = features.map((feature) => stamp(feature))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,10 +428,6 @@ export class DataLayer extends ServerStored {
|
||||||
if (idx !== -1) this._propertiesIndex.splice(idx, 1)
|
if (idx !== -1) this._propertiesIndex.splice(idx, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
allProperties() {
|
|
||||||
return this._propertiesIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
sortedValues(property) {
|
sortedValues(property) {
|
||||||
return Object.values(this._features)
|
return Object.values(this._features)
|
||||||
.map((feature) => feature.properties[property])
|
.map((feature) => feature.properties[property])
|
||||||
|
@ -450,11 +446,6 @@ export class DataLayer extends ServerStored {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sortFeatures(collection) {
|
|
||||||
const sortKeys = this._umap.getProperty('sortKey') || U.DEFAULT_LABEL_KEY
|
|
||||||
return Utils.sortFeatures(collection, sortKeys, U.lang)
|
|
||||||
}
|
|
||||||
|
|
||||||
makeFeatures(geojson = {}, sync = true) {
|
makeFeatures(geojson = {}, sync = true) {
|
||||||
if (geojson.type === 'Feature' || geojson.coordinates) {
|
if (geojson.type === 'Feature' || geojson.coordinates) {
|
||||||
geojson = [geojson]
|
geojson = [geojson]
|
||||||
|
@ -463,7 +454,7 @@ export class DataLayer extends ServerStored {
|
||||||
? geojson
|
? geojson
|
||||||
: geojson.features || geojson.geometries
|
: geojson.features || geojson.geometries
|
||||||
if (!collection) return
|
if (!collection) return
|
||||||
this.sortFeatures(collection)
|
Utils.sortFeatures(collection, this._umap.getProperty('sortKey'), U.lang)
|
||||||
for (const feature of collection) {
|
for (const feature of collection) {
|
||||||
this.makeFeature(feature, sync)
|
this.makeFeature(feature, sync)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { uMapAlert as Alert } from '../components/alerts/alert.js'
|
import { uMapAlert as Alert } from '../components/alerts/alert.js'
|
||||||
import { AjaxAutocomplete, AjaxAutocompleteMultiple, AutocompleteDatalist } from './autocomplete.js'
|
import { AjaxAutocomplete, AjaxAutocompleteMultiple } from './autocomplete.js'
|
||||||
import Help from './help.js'
|
import Help from './help.js'
|
||||||
import { ServerRequest } from './request.js'
|
import { ServerRequest } from './request.js'
|
||||||
import { SCHEMA } from './schema.js'
|
import { SCHEMA } from './schema.js'
|
||||||
|
@ -17,7 +17,6 @@ window.U = {
|
||||||
Alert,
|
Alert,
|
||||||
AjaxAutocomplete,
|
AjaxAutocomplete,
|
||||||
AjaxAutocompleteMultiple,
|
AjaxAutocompleteMultiple,
|
||||||
AutocompleteDatalist,
|
|
||||||
Help,
|
Help,
|
||||||
Icon,
|
Icon,
|
||||||
LAYER_TYPES,
|
LAYER_TYPES,
|
||||||
|
|
|
@ -33,15 +33,15 @@ const TEMPLATE = `
|
||||||
<fieldset id="import-mode" class="formbox">
|
<fieldset id="import-mode" class="formbox">
|
||||||
<legend class="counter" data-help="importMode">${translate('Choose import mode')}</legend>
|
<legend class="counter" data-help="importMode">${translate('Choose import mode')}</legend>
|
||||||
<label>
|
<label>
|
||||||
<input type="radio" name="action" value="copy" checked onchange />
|
<input type="radio" name="action" value="copy" />
|
||||||
${translate('Copy into the layer')}
|
${translate('Copy into the layer')}
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input type="radio" name="action" value="link" onchange />
|
<input type="radio" name="action" value="link" />
|
||||||
${translate('Link to the layer as remote data')}
|
${translate('Link to the layer as remote data')}
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<input type="button" class="button primary" name="submit" value="${translate('Import data')}" disabled />
|
<input type="button" class="button" name="submit" value="${translate('Import data')}" />
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -121,11 +121,6 @@ export default class Importer extends Utils.WithTemplate {
|
||||||
return this.qs('textarea').value
|
return this.qs('textarea').value
|
||||||
}
|
}
|
||||||
|
|
||||||
set raw(value) {
|
|
||||||
this.qs('textarea').value = value
|
|
||||||
this.onChange()
|
|
||||||
}
|
|
||||||
|
|
||||||
get clear() {
|
get clear() {
|
||||||
return Boolean(this.qs('[name=clear]').checked)
|
return Boolean(this.qs('[name=clear]').checked)
|
||||||
}
|
}
|
||||||
|
@ -203,7 +198,6 @@ export default class Importer extends Utils.WithTemplate {
|
||||||
)
|
)
|
||||||
this.qs('[name=layer-name]').toggleAttribute('hidden', Boolean(this.layerId))
|
this.qs('[name=layer-name]').toggleAttribute('hidden', Boolean(this.layerId))
|
||||||
this.qs('#clear').toggleAttribute('hidden', !this.layerId)
|
this.qs('#clear').toggleAttribute('hidden', !this.layerId)
|
||||||
this.qs('[name=submit').toggleAttribute('disabled', !this.canSubmit())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onFileChange(e) {
|
onFileChange(e) {
|
||||||
|
@ -225,7 +219,6 @@ export default class Importer extends Utils.WithTemplate {
|
||||||
this.url = null
|
this.url = null
|
||||||
this.format = undefined
|
this.format = undefined
|
||||||
this.layerName = null
|
this.layerName = null
|
||||||
this.raw = null
|
|
||||||
const layerSelect = this.qs('[name="layer-id"]')
|
const layerSelect = this.qs('[name="layer-id"]')
|
||||||
layerSelect.innerHTML = ''
|
layerSelect.innerHTML = ''
|
||||||
this._umap.eachDataLayerReverse((datalayer) => {
|
this._umap.eachDataLayerReverse((datalayer) => {
|
||||||
|
@ -258,17 +251,6 @@ export default class Importer extends Utils.WithTemplate {
|
||||||
this.qs('[type=file]').showPicker()
|
this.qs('[type=file]').showPicker()
|
||||||
}
|
}
|
||||||
|
|
||||||
canSubmit() {
|
|
||||||
if (!this.format) return false
|
|
||||||
const hasFiles = Boolean(this.files.length)
|
|
||||||
const hasRaw = Boolean(this.raw)
|
|
||||||
const hasUrl = Boolean(this.url)
|
|
||||||
const hasAction = Boolean(this.action)
|
|
||||||
if (!hasFiles && !hasRaw && !hasUrl) return false
|
|
||||||
if (this.url) return hasAction
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
let hasErrors
|
let hasErrors
|
||||||
if (this.format === 'umap') {
|
if (this.format === 'umap') {
|
||||||
|
|
|
@ -2,8 +2,6 @@ import { DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
|
||||||
import { BaseAjax, SingleMixin } from '../autocomplete.js'
|
import { BaseAjax, SingleMixin } from '../autocomplete.js'
|
||||||
import * as Util from '../utils.js'
|
import * as Util from '../utils.js'
|
||||||
import { AutocompleteCommunes } from './communesfr.js'
|
import { AutocompleteCommunes } from './communesfr.js'
|
||||||
import { translate } from '../i18n.js'
|
|
||||||
import { uMapAlert as Alert } from '../../components/alerts/alert.js'
|
|
||||||
|
|
||||||
const TEMPLATE = `
|
const TEMPLATE = `
|
||||||
<h3>Cadastre</h3>
|
<h3>Cadastre</h3>
|
||||||
|
@ -58,8 +56,6 @@ export class Importer {
|
||||||
.open({
|
.open({
|
||||||
template: container,
|
template: container,
|
||||||
className: `${this.id} importer dark`,
|
className: `${this.id} importer dark`,
|
||||||
cancel: false,
|
|
||||||
accept: translate('Choose this data'),
|
|
||||||
})
|
})
|
||||||
.then(confirm)
|
.then(confirm)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,8 @@ class Autocomplete extends SingleMixin(BaseAjax) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Importer {
|
export class Importer {
|
||||||
constructor(umap, options = {}) {
|
constructor(map, options = {}) {
|
||||||
this.umap = umap
|
this.map = map
|
||||||
this.name = options.name || 'GeoDataMine'
|
this.name = options.name || 'GeoDataMine'
|
||||||
this.baseUrl = options?.url || 'https://geodatamine.fr'
|
this.baseUrl = options?.url || 'https://geodatamine.fr'
|
||||||
this.id = 'geodatamine'
|
this.id = 'geodatamine'
|
||||||
|
@ -49,7 +49,7 @@ export class Importer {
|
||||||
let boundaryName = null
|
let boundaryName = null
|
||||||
const container = DomUtil.create('div')
|
const container = DomUtil.create('div')
|
||||||
container.innerHTML = TEMPLATE
|
container.innerHTML = TEMPLATE
|
||||||
const response = await this.umap.request.get(`${this.baseUrl}/themes`)
|
const response = await importer.map.request.get(`${this.baseUrl}/themes`)
|
||||||
const select = container.querySelector('select')
|
const select = container.querySelector('select')
|
||||||
if (response?.ok) {
|
if (response?.ok) {
|
||||||
const { themes } = await response.json()
|
const { themes } = await response.json()
|
||||||
|
|
|
@ -53,15 +53,11 @@ export class Importer {
|
||||||
'https://photon.komoot.io/api?q={q}&layer=county&layer=city&layer=state'
|
'https://photon.komoot.io/api?q={q}&layer=county&layer=city&layer=state'
|
||||||
this.id = 'overpass'
|
this.id = 'overpass'
|
||||||
this.boundaryChoice = null
|
this.boundaryChoice = null
|
||||||
this.expression = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async open(importer) {
|
async open(importer) {
|
||||||
const container = DomUtil.create('div')
|
const container = DomUtil.create('div')
|
||||||
container.innerHTML = TEMPLATE
|
container.innerHTML = TEMPLATE
|
||||||
if (this.expression) {
|
|
||||||
container.querySelector('[name=tags]').value = this.expression
|
|
||||||
}
|
|
||||||
this.autocomplete = new Autocomplete(container.querySelector('#area'), {
|
this.autocomplete = new Autocomplete(container.querySelector('#area'), {
|
||||||
url: this.searchUrl,
|
url: this.searchUrl,
|
||||||
placeholder: translate(
|
placeholder: translate(
|
||||||
|
@ -84,7 +80,6 @@ export class Importer {
|
||||||
Alert.error(translate('Expression is empty'))
|
Alert.error(translate('Expression is empty'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.expression = form.tags
|
|
||||||
let tags = form.tags
|
let tags = form.tags
|
||||||
if (!tags.startsWith('[')) tags = `[${tags}]`
|
if (!tags.startsWith('[')) tags = `[${tags}]`
|
||||||
let area = '{south},{west},{north},{east}'
|
let area = '{south},{west},{north},{east}'
|
||||||
|
|
|
@ -44,12 +44,12 @@ const ControlsMixin = {
|
||||||
new U.DrawToolbar({ map: this }).addTo(this)
|
new U.DrawToolbar({ map: this }).addTo(this)
|
||||||
const editActions = [
|
const editActions = [
|
||||||
U.EditCaptionAction,
|
U.EditCaptionAction,
|
||||||
U.ImportAction,
|
U.EditPropertiesAction,
|
||||||
U.EditLayersAction,
|
U.EditLayersAction,
|
||||||
U.ChangeTileLayerAction,
|
U.ChangeTileLayerAction,
|
||||||
U.UpdateExtentAction,
|
U.UpdateExtentAction,
|
||||||
U.UpdatePermsAction,
|
U.UpdatePermsAction,
|
||||||
U.EditPropertiesAction,
|
U.ImportAction,
|
||||||
]
|
]
|
||||||
if (this.options.editMode === 'advanced') {
|
if (this.options.editMode === 'advanced') {
|
||||||
new U.SettingsToolbar({ actions: editActions }).addTo(this)
|
new U.SettingsToolbar({ actions: editActions }).addTo(this)
|
||||||
|
|
|
@ -115,9 +115,7 @@ class Table extends TitleMixin(PopupTemplate) {
|
||||||
const table = document.createElement('table')
|
const table = document.createElement('table')
|
||||||
|
|
||||||
for (const key in feature.properties) {
|
for (const key in feature.properties) {
|
||||||
if (typeof feature.properties[key] === 'object' || U.LABEL_KEYS.includes(key)) {
|
if (typeof feature.properties[key] === 'object' || key === 'name') continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
table.appendChild(this.makeRow(feature, key))
|
table.appendChild(this.makeRow(feature, key))
|
||||||
}
|
}
|
||||||
return table
|
return table
|
||||||
|
@ -152,19 +150,6 @@ class GeoRSSLink extends PopupTemplate {
|
||||||
}
|
}
|
||||||
|
|
||||||
class OSM extends TitleMixin(PopupTemplate) {
|
class OSM extends TitleMixin(PopupTemplate) {
|
||||||
renderTitle(feature) {
|
|
||||||
const title = DomUtil.add('h3', 'popup-title')
|
|
||||||
const color = feature.getPreviewColor()
|
|
||||||
title.style.backgroundColor = color
|
|
||||||
const iconUrl = feature.getDynamicOption('iconUrl')
|
|
||||||
const icon = Icon.makeElement(iconUrl, title)
|
|
||||||
DomUtil.addClass(icon, 'icon')
|
|
||||||
Icon.setContrast(icon, title, iconUrl, color)
|
|
||||||
if (DomUtil.contrastedColor(title, color)) title.style.color = 'white'
|
|
||||||
DomUtil.add('span', '', title, this.getName(feature))
|
|
||||||
return title
|
|
||||||
}
|
|
||||||
|
|
||||||
getName(feature) {
|
getName(feature) {
|
||||||
const props = feature.properties
|
const props = feature.properties
|
||||||
const locale = getLocale()
|
const locale = getLocale()
|
||||||
|
@ -175,6 +160,15 @@ class OSM extends TitleMixin(PopupTemplate) {
|
||||||
renderBody(feature) {
|
renderBody(feature) {
|
||||||
const props = feature.properties
|
const props = feature.properties
|
||||||
const body = document.createElement('div')
|
const body = document.createElement('div')
|
||||||
|
const title = DomUtil.add('h3', 'popup-title', container)
|
||||||
|
const color = feature.getPreviewColor()
|
||||||
|
title.style.backgroundColor = color
|
||||||
|
const iconUrl = feature.getDynamicOption('iconUrl')
|
||||||
|
const icon = Icon.makeElement(iconUrl, title)
|
||||||
|
DomUtil.addClass(icon, 'icon')
|
||||||
|
Icon.setContrast(icon, title, iconUrl, color)
|
||||||
|
if (DomUtil.contrastedColor(title, color)) title.style.color = 'white'
|
||||||
|
DomUtil.add('span', '', title, this.getName(feature))
|
||||||
const street = props['addr:street']
|
const street = props['addr:street']
|
||||||
if (street) {
|
if (street) {
|
||||||
const row = DomUtil.add('address', 'address', body)
|
const row = DomUtil.add('address', 'address', body)
|
||||||
|
@ -211,13 +205,6 @@ class OSM extends TitleMixin(PopupTemplate) {
|
||||||
Utils.loadTemplate(`<div><a href="mailto:${email}">${email}</a></div>`)
|
Utils.loadTemplate(`<div><a href="mailto:${email}">${email}</a></div>`)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (props.panoramax) {
|
|
||||||
body.appendChild(
|
|
||||||
Utils.loadTemplate(
|
|
||||||
`<div><img src="https://api.panoramax.xyz/api/pictures/${props.panoramax}/sd.jpg" /></div>`
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
const id = props['@id'] || props.id
|
const id = props['@id'] || props.id
|
||||||
if (id) {
|
if (id) {
|
||||||
body.appendChild(
|
body.appendChild(
|
||||||
|
|
|
@ -75,7 +75,7 @@ const FeatureMixin = {
|
||||||
|
|
||||||
resetTooltip: function () {
|
resetTooltip: function () {
|
||||||
if (!this.feature.hasGeom()) return
|
if (!this.feature.hasGeom()) return
|
||||||
const displayName = this.feature.getDisplayName()
|
const displayName = this.feature.getDisplayName(null)
|
||||||
let showLabel = this.feature.getOption('showLabel')
|
let showLabel = this.feature.getOption('showLabel')
|
||||||
const oldLabelHover = this.feature.getOption('labelHover')
|
const oldLabelHover = this.feature.getOption('labelHover')
|
||||||
|
|
||||||
|
@ -255,10 +255,7 @@ const PathMixin = {
|
||||||
if (this._map.measureTools?.enabled()) {
|
if (this._map.measureTools?.enabled()) {
|
||||||
this._map._umap.tooltip.open({ content: this.getMeasure(), anchor: this })
|
this._map._umap.tooltip.open({ content: this.getMeasure(), anchor: this })
|
||||||
} else if (this._map._umap.editEnabled && !this._map._umap.editedFeature) {
|
} else if (this._map._umap.editEnabled && !this._map._umap.editedFeature) {
|
||||||
this._map._umap.tooltip.open({
|
this._map._umap.tooltip.open({ content: translate('Click to edit'), anchor: this })
|
||||||
content: translate('Click to edit'),
|
|
||||||
anchor: this,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -270,9 +267,7 @@ const PathMixin = {
|
||||||
this._map.once('moveend', this.makeGeometryEditable, this)
|
this._map.once('moveend', this.makeGeometryEditable, this)
|
||||||
const pointsCount = this._parts.reduce((acc, part) => acc + part.length, 0)
|
const pointsCount = this._parts.reduce((acc, part) => acc + part.length, 0)
|
||||||
if (pointsCount > 100 && this._map.getZoom() < this._map.getMaxZoom()) {
|
if (pointsCount > 100 && this._map.getZoom() < this._map.getMaxZoom()) {
|
||||||
this._map._umap.tooltip.open({
|
this._map._umap.tooltip.open({ content: L._('Please zoom in to edit the geometry') })
|
||||||
content: L._('Please zoom in to edit the geometry'),
|
|
||||||
})
|
|
||||||
this.disableEdit()
|
this.disableEdit()
|
||||||
} else {
|
} else {
|
||||||
this.enableEdit()
|
this.enableEdit()
|
||||||
|
@ -385,19 +380,8 @@ export const LeafletPolyline = Polyline.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
getMeasure: function (shape) {
|
getMeasure: function (shape) {
|
||||||
let shapes
|
|
||||||
if (shape) {
|
|
||||||
shapes = [shape]
|
|
||||||
} else if (LineUtil.isFlat(this._latlngs)) {
|
|
||||||
shapes = [this._latlngs]
|
|
||||||
} else {
|
|
||||||
shapes = this._latlngs
|
|
||||||
}
|
|
||||||
// FIXME: compute from data in feature (with TurfJS)
|
// FIXME: compute from data in feature (with TurfJS)
|
||||||
const length = shapes.reduce(
|
const length = L.GeoUtil.lineLength(this._map, shape || this._defaultShape())
|
||||||
(acc, shape) => acc + L.GeoUtil.lineLength(this._map, shape),
|
|
||||||
0
|
|
||||||
)
|
|
||||||
return L.GeoUtil.readableDistance(length, this._map.measureTools.getMeasureUnit())
|
return L.GeoUtil.readableDistance(length, this._map.measureTools.getMeasureUnit())
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -105,7 +105,7 @@ export default class TableEditor extends WithTemplate {
|
||||||
resetProperties() {
|
resetProperties() {
|
||||||
this.properties = this.datalayer._propertiesIndex
|
this.properties = this.datalayer._propertiesIndex
|
||||||
if (this.properties.length === 0) {
|
if (this.properties.length === 0) {
|
||||||
this.properties = [U.DEFAULT_LABEL_KEY, 'description']
|
this.properties = ['name', 'description']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,10 +71,6 @@ export default class Umap extends ServerStored {
|
||||||
// To be used in javascript APIs
|
// To be used in javascript APIs
|
||||||
if (geojson.properties.lang) U.lang = geojson.properties.lang
|
if (geojson.properties.lang) U.lang = geojson.properties.lang
|
||||||
|
|
||||||
// Make it available to utils, without needing a reference to `Umap`.
|
|
||||||
U.LABEL_KEYS = geojson.properties.defaultLabelKeys || []
|
|
||||||
U.DEFAULT_LABEL_KEY = U.LABEL_KEYS[0] || 'name'
|
|
||||||
|
|
||||||
this.setPropertiesFromQueryString()
|
this.setPropertiesFromQueryString()
|
||||||
|
|
||||||
// Needed for actions labels
|
// Needed for actions labels
|
||||||
|
@ -541,10 +537,10 @@ export default class Umap extends ServerStored {
|
||||||
this._leafletMap.editTools.startPolyline()
|
this._leafletMap.editTools.startPolyline()
|
||||||
break
|
break
|
||||||
case 'i':
|
case 'i':
|
||||||
this.importer.open()
|
this._leafletMap.importer.open()
|
||||||
break
|
break
|
||||||
case 'o':
|
case 'o':
|
||||||
this.importer.openFiles()
|
this._leafletMap.importer.openFiles()
|
||||||
break
|
break
|
||||||
case 'h':
|
case 'h':
|
||||||
this.help.showGetStarted()
|
this.help.showGetStarted()
|
||||||
|
@ -600,7 +596,7 @@ export default class Umap extends ServerStored {
|
||||||
const panes = this._leafletMap.getPane('overlayPane')
|
const panes = this._leafletMap.getPane('overlayPane')
|
||||||
|
|
||||||
this.datalayersIndex = []
|
this.datalayersIndex = []
|
||||||
for (const pane of panes.children) {
|
for (const pane of panes) {
|
||||||
if (!pane.dataset || !pane.dataset.id) continue
|
if (!pane.dataset || !pane.dataset.id) continue
|
||||||
this.datalayersIndex.push(this.datalayers[pane.dataset.id])
|
this.datalayersIndex.push(this.datalayers[pane.dataset.id])
|
||||||
}
|
}
|
||||||
|
@ -688,7 +684,7 @@ export default class Umap extends ServerStored {
|
||||||
}
|
}
|
||||||
|
|
||||||
allProperties() {
|
allProperties() {
|
||||||
return [].concat(...this.datalayersIndex.map((dl) => dl.allProperties()))
|
return [].concat(...this.datalayersIndex.map((dl) => dl._propertiesIndex))
|
||||||
}
|
}
|
||||||
|
|
||||||
sortedValues(property) {
|
sortedValues(property) {
|
||||||
|
@ -1429,13 +1425,13 @@ export default class Umap extends ServerStored {
|
||||||
row.dataset.id = stamp(datalayer)
|
row.dataset.id = stamp(datalayer)
|
||||||
})
|
})
|
||||||
const onReorder = (src, dst, initialIndex, finalIndex) => {
|
const onReorder = (src, dst, initialIndex, finalIndex) => {
|
||||||
const movedLayer = this.datalayers[src.dataset.id]
|
const layer = this.datalayers[src.dataset.id]
|
||||||
const targetLayer = this.datalayers[dst.dataset.id]
|
const other = this.datalayers[dst.dataset.id]
|
||||||
const minIndex = Math.min(movedLayer.getRank(), targetLayer.getRank())
|
const minIndex = Math.min(layer.getRank(), other.getRank())
|
||||||
const maxIndex = Math.max(movedLayer.getRank(), targetLayer.getRank())
|
const maxIndex = Math.max(layer.getRank(), other.getRank())
|
||||||
if (finalIndex === 0) movedLayer.bringToTop()
|
if (finalIndex === 0) layer.bringToTop()
|
||||||
else if (finalIndex > initialIndex) movedLayer.insertBefore(targetLayer)
|
else if (finalIndex > initialIndex) layer.insertBefore(other)
|
||||||
else movedLayer.insertAfter(targetLayer)
|
else layer.insertAfter(other)
|
||||||
this.eachDataLayerReverse((datalayer) => {
|
this.eachDataLayerReverse((datalayer) => {
|
||||||
if (datalayer.getRank() >= minIndex && datalayer.getRank() <= maxIndex)
|
if (datalayer.getRank() >= minIndex && datalayer.getRank() <= maxIndex)
|
||||||
datalayer.isDirty = true
|
datalayer.isDirty = true
|
||||||
|
|
|
@ -292,7 +292,7 @@ export function naturalSort(a, b, lang) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sortFeatures(features, sortKey, lang) {
|
export function sortFeatures(features, sortKey, lang) {
|
||||||
const sortKeys = sortKey.split(',')
|
const sortKeys = (sortKey || 'name').split(',')
|
||||||
|
|
||||||
const sort = (a, b, i) => {
|
const sort = (a, b, i) => {
|
||||||
let sortKey = sortKeys[i]
|
let sortKey = sortKeys[i]
|
||||||
|
|
|
@ -170,43 +170,22 @@ L.DomUtil.contrastWCAG21 = (rgb) => {
|
||||||
const contrast = (whiteLum + 0.05) / (lum + 0.05)
|
const contrast = (whiteLum + 0.05) / (lum + 0.05)
|
||||||
return contrast > 3 ? 1 : 0
|
return contrast > 3 ? 1 : 0
|
||||||
}
|
}
|
||||||
L.DomUtil.colorNameToHex = (str) => {
|
|
||||||
const ctx = document.createElement('canvas').getContext('2d')
|
|
||||||
ctx.fillStyle = str
|
|
||||||
return ctx.fillStyle
|
|
||||||
}
|
|
||||||
L.DomUtil.hexToRGB = (hex) => {
|
|
||||||
return hex
|
|
||||||
.replace(
|
|
||||||
/^#?([a-f\d])([a-f\d])([a-f\d])$/i,
|
|
||||||
(m, r, g, b) => `#${r}${r}${g}${g}${b}${b}`
|
|
||||||
)
|
|
||||||
.substring(1)
|
|
||||||
.match(/.{2}/g)
|
|
||||||
.map((x) => Number.parseInt(x, 16))
|
|
||||||
}
|
|
||||||
|
|
||||||
const _CACHE_CONSTRAST = {}
|
const _CACHE_CONSTRAST = {}
|
||||||
L.DomUtil.contrastedColor = (el, bgcolor) => {
|
L.DomUtil.contrastedColor = (el, bgcolor) => {
|
||||||
// Return 0 for black and 1 for white
|
// Return 0 for black and 1 for white
|
||||||
// bgcolor is a human color, it can be a any keyword (purple…)
|
// bgcolor is a human color, it can be a any keyword (purple…)
|
||||||
if (typeof _CACHE_CONSTRAST[bgcolor] !== 'undefined') return _CACHE_CONSTRAST[bgcolor]
|
if (typeof _CACHE_CONSTRAST[bgcolor] !== 'undefined') return _CACHE_CONSTRAST[bgcolor]
|
||||||
|
let out = 0
|
||||||
let rgb = window.getComputedStyle(el).getPropertyValue('background-color')
|
let rgb = window.getComputedStyle(el).getPropertyValue('background-color')
|
||||||
rgb = L.DomUtil.RGBRegex.exec(rgb)
|
rgb = L.DomUtil.RGBRegex.exec(rgb)
|
||||||
if (rgb && rgb.length === 4) {
|
if (!rgb || rgb.length !== 4) return out
|
||||||
rgb = [
|
rgb = [
|
||||||
Number.parseInt(rgb[1], 10),
|
Number.parseInt(rgb[1], 10),
|
||||||
Number.parseInt(rgb[2], 10),
|
Number.parseInt(rgb[2], 10),
|
||||||
Number.parseInt(rgb[3], 10),
|
Number.parseInt(rgb[3], 10),
|
||||||
]
|
]
|
||||||
} else {
|
out = L.DomUtil.contrastWCAG21(rgb)
|
||||||
// The element may not yet be added to the DOM, so let's try
|
|
||||||
// another way
|
|
||||||
const hex = L.DomUtil.colorNameToHex(bgcolor)
|
|
||||||
rgb = L.DomUtil.hexToRGB(hex)
|
|
||||||
}
|
|
||||||
if (!rgb) return 1
|
|
||||||
const out = L.DomUtil.contrastWCAG21(rgb)
|
|
||||||
if (bgcolor) _CACHE_CONSTRAST[bgcolor] = out
|
if (bgcolor) _CACHE_CONSTRAST[bgcolor] = out
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
|
@ -448,17 +448,6 @@ L.FormBuilder.BlurInput.include({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// Adds an autocomplete using all available user defined properties
|
|
||||||
L.FormBuilder.PropertyInput = L.FormBuilder.BlurInput.extend({
|
|
||||||
build: function () {
|
|
||||||
L.FormBuilder.BlurInput.prototype.build.call(this)
|
|
||||||
const autocomplete = new U.AutocompleteDatalist(this.input)
|
|
||||||
// Will be used on Umap and DataLayer
|
|
||||||
const properties = this.builder.obj.allProperties()
|
|
||||||
autocomplete.suggestions = properties
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({
|
L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({
|
||||||
type: () => 'hidden',
|
type: () => 'hidden',
|
||||||
|
|
||||||
|
@ -1121,11 +1110,10 @@ U.FormBuilder = L.FormBuilder.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
customHandlers: {
|
customHandlers: {
|
||||||
sortKey: 'PropertyInput',
|
sortKey: 'BlurInput',
|
||||||
easing: 'Switch',
|
easing: 'Switch',
|
||||||
facetKey: 'PropertyInput',
|
facetKey: 'BlurInput',
|
||||||
slugKey: 'PropertyInput',
|
slugKey: 'BlurInput',
|
||||||
labelKey: 'PropertyInput',
|
|
||||||
},
|
},
|
||||||
|
|
||||||
computeDefaultOptions: function () {
|
computeDefaultOptions: function () {
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
|
@ -15,12 +15,7 @@ DATALAYER_DATA = {
|
||||||
"features": [
|
"features": [
|
||||||
{
|
{
|
||||||
"type": "Feature",
|
"type": "Feature",
|
||||||
"properties": {
|
"properties": {"name": "one point in france", "foo": "point", "bar": "one"},
|
||||||
"name": "one point in france",
|
|
||||||
"foo": "point",
|
|
||||||
"bar": "one",
|
|
||||||
"label": "this is label one",
|
|
||||||
},
|
|
||||||
"geometry": {"type": "Point", "coordinates": [3.339844, 46.920255]},
|
"geometry": {"type": "Point", "coordinates": [3.339844, 46.920255]},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -29,7 +24,6 @@ DATALAYER_DATA = {
|
||||||
"name": "one polygon in greenland",
|
"name": "one polygon in greenland",
|
||||||
"foo": "polygon",
|
"foo": "polygon",
|
||||||
"bar": "two",
|
"bar": "two",
|
||||||
"label": "this is label two",
|
|
||||||
},
|
},
|
||||||
"geometry": {
|
"geometry": {
|
||||||
"type": "Polygon",
|
"type": "Polygon",
|
||||||
|
@ -50,7 +44,6 @@ DATALAYER_DATA = {
|
||||||
"name": "one line in new zeland",
|
"name": "one line in new zeland",
|
||||||
"foo": "line",
|
"foo": "line",
|
||||||
"bar": "three",
|
"bar": "three",
|
||||||
"label": "this is label three",
|
|
||||||
},
|
},
|
||||||
"geometry": {
|
"geometry": {
|
||||||
"type": "LineString",
|
"type": "LineString",
|
||||||
|
@ -483,11 +476,3 @@ def test_main_toolbox_toggle_all_layers(live_server, map, page):
|
||||||
# Should hidden again all layers
|
# Should hidden again all layers
|
||||||
expect(page.locator(".datalayer.off")).to_have_count(3)
|
expect(page.locator(".datalayer.off")).to_have_count(3)
|
||||||
expect(markers).to_have_count(0)
|
expect(markers).to_have_count(0)
|
||||||
|
|
||||||
|
|
||||||
def test_honour_the_label_fields_settings(live_server, map, page, bootstrap, settings):
|
|
||||||
settings.UMAP_LABEL_KEYS = ["label", "name"]
|
|
||||||
page.goto(f"{live_server.url}{map.get_absolute_url()}")
|
|
||||||
expect(page.locator(".panel").get_by_text("this is label one")).to_be_visible()
|
|
||||||
expect(page.locator(".panel").get_by_text("this is label two")).to_be_visible()
|
|
||||||
expect(page.locator(".panel").get_by_text("this is label three")).to_be_visible()
|
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
import pytest
|
|
||||||
from playwright.sync_api import expect
|
|
||||||
|
|
||||||
from ..base import DataLayerFactory
|
|
||||||
|
|
||||||
pytestmark = pytest.mark.django_db
|
|
||||||
|
|
||||||
OSM_DATA = {
|
|
||||||
"type": "FeatureCollection",
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"type": "Feature",
|
|
||||||
"geometry": {"type": "Point", "coordinates": [2.49, 48.79]},
|
|
||||||
"properties": {
|
|
||||||
"amenity": "restaurant",
|
|
||||||
"cuisine": "italian",
|
|
||||||
"name": "A Casa di Nonna",
|
|
||||||
"panoramax": "d811b398-d930-4cf8-95a2-0c29c34d9fca",
|
|
||||||
"phone": "+33 1 48 89 54 12",
|
|
||||||
"takeaway:covid19": "yes",
|
|
||||||
"wheelchair": "no",
|
|
||||||
"id": "node/1130849864",
|
|
||||||
},
|
|
||||||
"id": "AzMjk",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"_umap_options": {
|
|
||||||
"popupTemplate": "OSM",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def test_openstreetmap_popup(live_server, map, page):
|
|
||||||
DataLayerFactory(map=map, data=OSM_DATA)
|
|
||||||
page.goto(f"{live_server.url}{map.get_absolute_url()}#18/48.79/2.49")
|
|
||||||
expect(page.locator(".umap-icon-active")).to_be_hidden()
|
|
||||||
page.locator(".leaflet-marker-icon").click()
|
|
||||||
expect(page.get_by_role("heading", name="A Casa di Nonna")).to_be_visible()
|
|
||||||
expect(page.get_by_text("+33 1 48 89 54 12")).to_be_visible()
|
|
||||||
img = page.locator(".umap-popup-content img")
|
|
||||||
expect(img).to_have_attribute(
|
|
||||||
"src",
|
|
||||||
"https://api.panoramax.xyz/api/pictures/d811b398-d930-4cf8-95a2-0c29c34d9fca/sd.jpg",
|
|
||||||
)
|
|
|
@ -49,37 +49,3 @@ def test_should_open_popup_on_click(live_server, map, page, bootstrap):
|
||||||
# Close popup
|
# Close popup
|
||||||
page.locator("#map").click()
|
page.locator("#map").click()
|
||||||
expect(line).to_have_attribute("stroke-opacity", "0.5")
|
expect(line).to_have_attribute("stroke-opacity", "0.5")
|
||||||
|
|
||||||
|
|
||||||
def test_can_use_measure_on_name(live_server, map, page):
|
|
||||||
data = {
|
|
||||||
"type": "FeatureCollection",
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"type": "Feature",
|
|
||||||
"properties": {"name": "linestring"},
|
|
||||||
"geometry": {
|
|
||||||
"type": "LineString",
|
|
||||||
"coordinates": [
|
|
||||||
[11.25, 53.585984],
|
|
||||||
[10.151367, 52.975108],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Feature",
|
|
||||||
"properties": {"name": "multilinestring"},
|
|
||||||
"geometry": {
|
|
||||||
"type": "MultiLineString",
|
|
||||||
"coordinates": [[[8, 53], [13, 52]], [[12, 51], [15, 52]]],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
map.settings["properties"]["labelKey"] = "{name} ({measure})"
|
|
||||||
map.settings["properties"]["onLoadPanel"] = "databrowser"
|
|
||||||
map.save()
|
|
||||||
DataLayerFactory(map=map, data=data)
|
|
||||||
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/10/50")
|
|
||||||
expect(page.get_by_text("linestring (99.7 km)")).to_be_visible()
|
|
||||||
expect(page.get_by_text("multilinestring (592 km)")).to_be_visible()
|
|
||||||
|
|
|
@ -609,7 +609,6 @@ class MapDetailMixin(SessionMixin):
|
||||||
"websocketEnabled": settings.WEBSOCKET_ENABLED,
|
"websocketEnabled": settings.WEBSOCKET_ENABLED,
|
||||||
"websocketURI": settings.WEBSOCKET_FRONT_URI,
|
"websocketURI": settings.WEBSOCKET_FRONT_URI,
|
||||||
"importers": settings.UMAP_IMPORTERS,
|
"importers": settings.UMAP_IMPORTERS,
|
||||||
"defaultLabelKeys": settings.UMAP_LABEL_KEYS,
|
|
||||||
}
|
}
|
||||||
created = bool(getattr(self, "object", None))
|
created = bool(getattr(self, "object", None))
|
||||||
if (created and self.object.owner) or (not created and not user.is_anonymous):
|
if (created and self.object.owner) or (not created and not user.is_anonymous):
|
||||||
|
|
Loading…
Reference in a new issue