mirror of
https://github.com/umap-project/umap.git
synced 2025-05-06 06:21:49 +02:00
WIP
This commit is contained in:
parent
d15c436d42
commit
68e47cfdcc
12 changed files with 1600 additions and 139 deletions
11
.eslintrc
Normal file
11
.eslintrc
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
{
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 7
|
||||||
|
},
|
||||||
|
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"node": true
|
||||||
|
}
|
||||||
|
}
|
8
TODO.md
Normal file
8
TODO.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
- [ ] Utiliser un module ES6 avec les autres modules exposés globalement.
|
||||||
|
- [ ] Changer la manière dont les requêtes sont faites vers le serveur lors des sauvegardes.
|
||||||
|
|
||||||
|
|
||||||
|
## Explications utiles
|
||||||
|
|
||||||
|
- [ ] Pourquoi est-ce c'est le serveur qui envoie les URLs au client ?
|
||||||
|
- [ ]
|
1445
package-lock.json
generated
1445
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -7,6 +7,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"chai": "^3.3.0",
|
"chai": "^3.3.0",
|
||||||
|
"eslint": "^8.55.0",
|
||||||
"happen": "~0.1.3",
|
"happen": "~0.1.3",
|
||||||
"lebab": "^3.2.1",
|
"lebab": "^3.2.1",
|
||||||
"mocha": "^10.2.0",
|
"mocha": "^10.2.0",
|
||||||
|
|
5
umap/static/umap/js/bindModules.mjs
Normal file
5
umap/static/umap/js/bindModules.mjs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import SyncStorage from "./modules/syncStorage.mjs"
|
||||||
|
import URLs from "./modules/urls.mjs"
|
||||||
|
|
||||||
|
window.URLs = URLs;
|
||||||
|
window.SyncStorage = SyncStorage;
|
78
umap/static/umap/js/modules/syncStorage.mjs
Normal file
78
umap/static/umap/js/modules/syncStorage.mjs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
class SyncStorage{
|
||||||
|
constructor(urls){
|
||||||
|
this.urls = urls;
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveMap(map){
|
||||||
|
const geojson = {
|
||||||
|
type: 'Feature',
|
||||||
|
geometry: map.geometry(),
|
||||||
|
properties: map.exportOptions(),
|
||||||
|
}
|
||||||
|
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('name', this.options.name)
|
||||||
|
formData.append('center', JSON.stringify(this.geometry()))
|
||||||
|
formData.append('settings', JSON.stringify(geojson))
|
||||||
|
data = await this.post(this.urls.saveMap(), {
|
||||||
|
data: formData,
|
||||||
|
context: this,
|
||||||
|
});
|
||||||
|
|
||||||
|
let duration = 3000;
|
||||||
|
let alert = { content: L._('Map has been saved!'), level: 'info' }
|
||||||
|
|
||||||
|
if (!map.options.umap_id) {
|
||||||
|
alert.content = L._('Congratulations, your map has been created!');
|
||||||
|
map.options.umap_id = data.id
|
||||||
|
map.permissions.setOptions(data.permissions)
|
||||||
|
map.permissions.commit()
|
||||||
|
if (
|
||||||
|
data.permissions &&
|
||||||
|
data.permissions.anonymous_edit_url &&
|
||||||
|
map.options.urls.map_send_edit_link
|
||||||
|
) {
|
||||||
|
alert.duration = Infinity
|
||||||
|
alert.content =
|
||||||
|
L._(
|
||||||
|
'Your map has been created! As you are not logged in, here is your secret link to edit the map, please keep it safe:'
|
||||||
|
) + `<br>${data.permissions.anonymous_edit_url}`
|
||||||
|
|
||||||
|
alert.actions = [
|
||||||
|
{
|
||||||
|
label: L._('Send me the link'),
|
||||||
|
input: L._('Email'),
|
||||||
|
callback: map.sendEditLink,
|
||||||
|
callbackContext: map,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: L._('Copy link'),
|
||||||
|
callback: () => {
|
||||||
|
L.Util.copyToClipboard(data.permissions.anonymous_edit_url)
|
||||||
|
map.ui.alert({
|
||||||
|
content: L._('Secret edit link copied to clipboard!'),
|
||||||
|
level: 'info',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
callbackContext: map,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
} else if (!map.permissions.isDirty) {
|
||||||
|
// Do not override local changes to permissions,
|
||||||
|
// but update in case some other editors changed them in the meantime.
|
||||||
|
map.permissions.setOptions(data.permissions)
|
||||||
|
map.permissions.commit()
|
||||||
|
}
|
||||||
|
// Update URL in case the name has changed.
|
||||||
|
if (history && history.pushState)
|
||||||
|
history.pushState({}, map.options.name, data.url)
|
||||||
|
else window.location = data.url
|
||||||
|
alert.content = data.info || alert.content
|
||||||
|
map.once('saved', () => map.ui.alert(alert))
|
||||||
|
map.ui.closePanel()
|
||||||
|
map.permissions.save()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SyncStorage;
|
56
umap/static/umap/js/modules/urls.mjs
Normal file
56
umap/static/umap/js/modules/urls.mjs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
export default class URLs{
|
||||||
|
constructor(serverUrls){
|
||||||
|
this.urls = serverUrls;
|
||||||
|
console.log(`got server urls = ${serverUrls}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
get(urlName, params) {
|
||||||
|
return L.Util.template(this.urls[urlName], ...params);
|
||||||
|
}
|
||||||
|
|
||||||
|
editMap(mapId) {
|
||||||
|
return L.Util.template(this.urls.map_update, {
|
||||||
|
map_id: mapId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
createMap() {
|
||||||
|
return L.Util.template(this.urls.map_create)
|
||||||
|
}
|
||||||
|
|
||||||
|
saveMap(mapId) {
|
||||||
|
if (mapId)
|
||||||
|
return this.getEditUrl(mapId);
|
||||||
|
return this.getCreateUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteMap(mapId) {
|
||||||
|
return L.Util.template(this.options.urls.map_delete, {
|
||||||
|
map_id: mapId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
starMap(mapId) {
|
||||||
|
return L.Util.template(this.urls.map_star, {
|
||||||
|
map_id: mapId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cloneMap(mapId) {
|
||||||
|
return L.Util.template(this.urls.map_clone, {
|
||||||
|
map_id: mapId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadMap(mapId) {
|
||||||
|
return L.Util.template(this.options.urls.map_download, {
|
||||||
|
map_id: mapId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
sendEditLink(mapId){
|
||||||
|
return L.Util.template(this.urls.map_send_edit_link, {
|
||||||
|
map_id: mapId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -73,7 +73,7 @@ L.U.Map.include({
|
||||||
// To be used in javascript APIs
|
// To be used in javascript APIs
|
||||||
if (geojson.properties.lang) L.lang = geojson.properties.lang
|
if (geojson.properties.lang) L.lang = geojson.properties.lang
|
||||||
|
|
||||||
// Don't let default autocreation of controls
|
// Don't let default auto-creation of controls
|
||||||
const zoomControl =
|
const zoomControl =
|
||||||
typeof geojson.properties.zoomControl !== 'undefined'
|
typeof geojson.properties.zoomControl !== 'undefined'
|
||||||
? geojson.properties.zoomControl
|
? geojson.properties.zoomControl
|
||||||
|
@ -88,8 +88,10 @@ L.U.Map.include({
|
||||||
|
|
||||||
L.Map.prototype.initialize.call(this, el, geojson.properties)
|
L.Map.prototype.initialize.call(this, el, geojson.properties)
|
||||||
|
|
||||||
// After calling parent initialize, as we are doing initCenter our-selves
|
// After calling parent initialize, as we are doing initCenter ourselves
|
||||||
if (geojson.geometry) this.options.center = this.latLng(geojson.geometry)
|
if (geojson.geometry) this.options.center = this.latLng(geojson.geometry)
|
||||||
|
this.urls = new window.URLs(this.options.urls);
|
||||||
|
this.storage = new window.SyncStorage(this, this.urls);
|
||||||
|
|
||||||
this.ui = new L.U.UI(this._container)
|
this.ui = new L.U.UI(this._container)
|
||||||
this.xhr = new L.U.Xhr(this.ui)
|
this.xhr = new L.U.Xhr(this.ui)
|
||||||
|
@ -273,9 +275,7 @@ L.U.Map.include({
|
||||||
history.pushState({}, '', url)
|
history.pushState({}, '', url)
|
||||||
}
|
}
|
||||||
if (L.Util.queryString('download'))
|
if (L.Util.queryString('download'))
|
||||||
window.location = L.Util.template(this.options.urls.map_download, {
|
window.location = this.urls.downloadMap(this.options.umap_id);
|
||||||
map_id: this.options.umap_id,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
window.onbeforeunload = () => this.isDirty || null
|
window.onbeforeunload = () => this.isDirty || null
|
||||||
|
@ -1083,97 +1083,25 @@ L.U.Map.include({
|
||||||
return properties
|
return properties
|
||||||
},
|
},
|
||||||
|
|
||||||
saveSelf: function () {
|
|
||||||
const geojson = {
|
|
||||||
type: 'Feature',
|
|
||||||
geometry: this.geometry(),
|
|
||||||
properties: this.exportOptions(),
|
|
||||||
}
|
|
||||||
const formData = new FormData()
|
|
||||||
formData.append('name', this.options.name)
|
|
||||||
formData.append('center', JSON.stringify(this.geometry()))
|
|
||||||
formData.append('settings', JSON.stringify(geojson))
|
|
||||||
this.post(this.getSaveUrl(), {
|
|
||||||
data: formData,
|
|
||||||
context: this,
|
|
||||||
callback: function (data) {
|
|
||||||
let duration = 3000,
|
|
||||||
alert = { content: L._('Map has been saved!'), level: 'info' }
|
|
||||||
if (!this.options.umap_id) {
|
|
||||||
alert.content = L._('Congratulations, your map has been created!')
|
|
||||||
this.options.umap_id = data.id
|
|
||||||
this.permissions.setOptions(data.permissions)
|
|
||||||
this.permissions.commit()
|
|
||||||
if (
|
|
||||||
data.permissions &&
|
|
||||||
data.permissions.anonymous_edit_url &&
|
|
||||||
this.options.urls.map_send_edit_link
|
|
||||||
) {
|
|
||||||
alert.duration = Infinity
|
|
||||||
alert.content =
|
|
||||||
L._(
|
|
||||||
'Your map has been created! As you are not logged in, here is your secret link to edit the map, please keep it safe:'
|
|
||||||
) + `<br>${data.permissions.anonymous_edit_url}`
|
|
||||||
|
|
||||||
alert.actions = [
|
|
||||||
{
|
|
||||||
label: L._('Send me the link'),
|
|
||||||
input: L._('Email'),
|
|
||||||
callback: this.sendEditLink,
|
|
||||||
callbackContext: this,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: L._('Copy link'),
|
|
||||||
callback: () => {
|
|
||||||
L.Util.copyToClipboard(data.permissions.anonymous_edit_url)
|
|
||||||
this.ui.alert({
|
|
||||||
content: L._('Secret edit link copied to clipboard!'),
|
|
||||||
level: 'info',
|
|
||||||
})
|
|
||||||
},
|
|
||||||
callbackContext: this,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
} else if (!this.permissions.isDirty) {
|
|
||||||
// Do not override local changes to permissions,
|
|
||||||
// but update in case some other editors changed them in the meantime.
|
|
||||||
this.permissions.setOptions(data.permissions)
|
|
||||||
this.permissions.commit()
|
|
||||||
}
|
|
||||||
// Update URL in case the name has changed.
|
|
||||||
if (history && history.pushState)
|
|
||||||
history.pushState({}, this.options.name, data.url)
|
|
||||||
else window.location = data.url
|
|
||||||
alert.content = data.info || alert.content
|
|
||||||
this.once('saved', () => this.ui.alert(alert))
|
|
||||||
this.ui.closePanel()
|
|
||||||
this.permissions.save()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
save: function () {
|
save: function () {
|
||||||
if (!this.isDirty) return
|
if (!this.isDirty) return
|
||||||
if (this._default_extent) this.updateExtent()
|
if (this._default_extent) this.updateExtent()
|
||||||
this.backup()
|
this.backup()
|
||||||
this.once('saved', () => {
|
this.once('saved', () => {
|
||||||
this.isDirty = false
|
this.isDirty = false
|
||||||
})
|
});
|
||||||
if (this.options.editMode === 'advanced') {
|
if (this.options.editMode === 'advanced') {
|
||||||
// Only save the map if the user has the rights to do so.
|
// Only save the map if the user has the rights to do so.
|
||||||
this.saveSelf()
|
this.storage.saveMap()
|
||||||
} else {
|
} else {
|
||||||
this.permissions.save()
|
this.permissions.save()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
sendEditLink: function () {
|
sendEditLink: function () {
|
||||||
const url = L.Util.template(this.options.urls.map_send_edit_link, {
|
const url = this.urls.get('sendEditLink', this.options.umap_id);
|
||||||
map_id: this.options.umap_id,
|
const input = this.ui._alert.querySelector('input');
|
||||||
}),
|
const email = input.value;
|
||||||
input = this.ui._alert.querySelector('input'),
|
|
||||||
email = input.value
|
|
||||||
|
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('email', email)
|
formData.append('email', email)
|
||||||
|
@ -1182,29 +1110,14 @@ L.U.Map.include({
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
getEditUrl: function () {
|
|
||||||
return L.Util.template(this.options.urls.map_update, {
|
|
||||||
map_id: this.options.umap_id,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
getCreateUrl: function () {
|
|
||||||
return L.Util.template(this.options.urls.map_create)
|
|
||||||
},
|
|
||||||
|
|
||||||
getSaveUrl: function () {
|
|
||||||
return (this.options.umap_id && this.getEditUrl()) || this.getCreateUrl()
|
|
||||||
},
|
|
||||||
|
|
||||||
star: function () {
|
star: function () {
|
||||||
if (!this.options.umap_id)
|
if (!this.options.umap_id)
|
||||||
return this.ui.alert({
|
return this.ui.alert({
|
||||||
content: L._('Please save the map first'),
|
content: L._('Please save the map first'),
|
||||||
level: 'error',
|
level: 'error',
|
||||||
})
|
})
|
||||||
let url = L.Util.template(this.options.urls.map_star, {
|
let url = this.urls.get("StarMap", this.options.umap_id);
|
||||||
map_id: this.options.umap_id,
|
|
||||||
})
|
|
||||||
this.post(url, {
|
this.post(url, {
|
||||||
context: this,
|
context: this,
|
||||||
callback: function (data) {
|
callback: function (data) {
|
||||||
|
@ -1812,9 +1725,7 @@ L.U.Map.include({
|
||||||
|
|
||||||
del: function () {
|
del: function () {
|
||||||
if (confirm(L._('Are you sure you want to delete this map?'))) {
|
if (confirm(L._('Are you sure you want to delete this map?'))) {
|
||||||
const url = L.Util.template(this.options.urls.map_delete, {
|
const url = this.urls.deleteMap(this.options.umap_id);
|
||||||
map_id: this.options.umap_id,
|
|
||||||
})
|
|
||||||
this.post(url)
|
this.post(url)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1823,10 +1734,7 @@ L.U.Map.include({
|
||||||
if (
|
if (
|
||||||
confirm(L._('Are you sure you want to clone this map and all its datalayers?'))
|
confirm(L._('Are you sure you want to clone this map and all its datalayers?'))
|
||||||
) {
|
) {
|
||||||
const url = L.Util.template(this.options.urls.map_clone, {
|
this.post(this.urls.cloneMap(this.options.umap_id));
|
||||||
map_id: this.options.umap_id,
|
|
||||||
})
|
|
||||||
this.post(url)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
{% block bottom_js %}
|
{% block bottom_js %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
<script type="text/javascript">
|
<script defer type="text/javascript">
|
||||||
!(function () {
|
!(function () {
|
||||||
const ui = new L.U.UI(document.querySelector('header'))
|
const ui = new L.U.UI(document.querySelector('header'))
|
||||||
const xhr = new L.U.Xhr(ui)
|
const xhr = new L.U.Xhr(ui)
|
||||||
|
|
|
@ -45,4 +45,5 @@
|
||||||
<script src="{{ STATIC_URL }}umap/js/umap.browser.js"></script>
|
<script src="{{ STATIC_URL }}umap/js/umap.browser.js"></script>
|
||||||
<script src="{{ STATIC_URL }}umap/js/umap.js"></script>
|
<script src="{{ STATIC_URL }}umap/js/umap.js"></script>
|
||||||
<script src="{{ STATIC_URL }}umap/js/umap.ui.js"></script>
|
<script src="{{ STATIC_URL }}umap/js/umap.ui.js"></script>
|
||||||
|
<script type="module" src="{{ STATIC_URL }}umap/js/bindModules.mjs"></script>
|
||||||
{% endcompress %}
|
{% endcompress %}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
{% load umap_tags %}
|
{% load umap_tags %}
|
||||||
<div id="{{ unique_id }}" class="map_fragment"></div>
|
<div id="{{ unique_id }}" class="map_fragment"></div>
|
||||||
<!-- djlint:off -->
|
<!-- djlint:off -->
|
||||||
<script type="text/javascript">
|
<script defer type="text/javascript">
|
||||||
new L.U.Map("{{ unique_id }}", {{ map_settings|notag|safe }})
|
window.addEventListener('load', (event) => {
|
||||||
|
new L.U.Map("{{ unique_id }}", {{ map_settings|notag|safe }})
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<!-- djlint:on -->
|
<!-- djlint:on -->
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
{% load umap_tags %}
|
{% load umap_tags %}
|
||||||
<div id="map"></div>
|
<div id="map"></div>
|
||||||
<!-- djlint:off -->
|
<!-- djlint:off -->
|
||||||
<script type="text/javascript">
|
<script defer type="text/javascript">
|
||||||
let MAP = new L.U.Map("map", {{ map_settings|notag|safe }})
|
window.addEventListener('load', (event) => {
|
||||||
|
let MAP = new L.U.Map("map", {{ map_settings|notag|safe }});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<!-- djlint:on -->
|
<!-- djlint:on -->
|
||||||
|
|
Loading…
Reference in a new issue