chore: move alert to dedicated module
This commit is contained in:
parent
03f6080148
commit
8ddc570e23
19 changed files with 214 additions and 208 deletions
|
@ -756,57 +756,6 @@ input[type=hidden].blur + [type="button"] {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* *********** */
|
|
||||||
/* Alerts */
|
|
||||||
/* *********** */
|
|
||||||
#umap-alert-container {
|
|
||||||
min-height: 46px;
|
|
||||||
line-height: 46px;
|
|
||||||
padding-left: 10px;
|
|
||||||
width: calc(100% - 500px);
|
|
||||||
position: absolute;
|
|
||||||
top: -46px;
|
|
||||||
left: 250px; /* Keep save/cancel button accessible. */
|
|
||||||
right: 250px;
|
|
||||||
box-shadow: 0 1px 7px #999999;
|
|
||||||
visibility: hidden;
|
|
||||||
background: none repeat scroll 0 0 rgba(20, 22, 23, 0.8);
|
|
||||||
font-weight: bold;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 0.8em;
|
|
||||||
z-index: 1012;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
#umap-alert-container.error {
|
|
||||||
background-color: #c60f13;
|
|
||||||
}
|
|
||||||
.umap-alert #umap-alert-container {
|
|
||||||
visibility: visible;
|
|
||||||
top: 23px;
|
|
||||||
}
|
|
||||||
.umap-alert-container .umap-action {
|
|
||||||
margin-left: 10px;
|
|
||||||
background-color: #fff;
|
|
||||||
color: #000;
|
|
||||||
padding: 5px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
.umap-alert-container .umap-action:hover {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
.umap-alert-container .error .umap-action {
|
|
||||||
background-color: #666;
|
|
||||||
color: #eee;
|
|
||||||
}
|
|
||||||
.umap-alert-container .error .umap-action:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.umap-alert-container input {
|
|
||||||
padding: 5px;
|
|
||||||
border-radius: 4px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* *********** */
|
/* *********** */
|
||||||
/* Tooltip */
|
/* Tooltip */
|
||||||
/* *********** */
|
/* *********** */
|
||||||
|
@ -870,32 +819,6 @@ input[type=hidden].blur + [type="button"] {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* *********** */
|
|
||||||
/* Close link */
|
|
||||||
/* *********** */
|
|
||||||
#umap-alert-container .umap-close-link {
|
|
||||||
color: #fff;
|
|
||||||
float: right;
|
|
||||||
padding-right: 10px;
|
|
||||||
width: 100px;
|
|
||||||
line-height: 1;
|
|
||||||
margin: .5rem;
|
|
||||||
background-color: #202425;
|
|
||||||
font-size: .7rem;
|
|
||||||
}
|
|
||||||
#umap-alert-container .umap-close-icon {
|
|
||||||
background-position: -74px -55px;
|
|
||||||
}
|
|
||||||
#umap-alert-container .umap-alert-actions {
|
|
||||||
display: flex;
|
|
||||||
margin: 1rem;
|
|
||||||
}
|
|
||||||
#umap-alert-container .umap-alert-actions .umap-action {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* *********** */
|
/* *********** */
|
||||||
/* Various */
|
/* Various */
|
||||||
/* *********** */
|
/* *********** */
|
||||||
|
@ -913,15 +836,3 @@ input[type=hidden].blur + [type="button"] {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* *********** */
|
|
||||||
/* Mobile */
|
|
||||||
/* *********** */
|
|
||||||
@media all and (orientation:portrait) {
|
|
||||||
#umap-alert-container {
|
|
||||||
width: 100%;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
75
umap/static/umap/css/alert.css
Normal file
75
umap/static/umap/css/alert.css
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#umap-alert-container {
|
||||||
|
min-height: 46px;
|
||||||
|
line-height: 46px;
|
||||||
|
padding-left: 10px;
|
||||||
|
width: calc(100% - 500px);
|
||||||
|
position: absolute;
|
||||||
|
top: -46px;
|
||||||
|
left: 250px; /* Keep save/cancel button accessible. */
|
||||||
|
right: 250px;
|
||||||
|
box-shadow: 0 1px 7px #999999;
|
||||||
|
visibility: hidden;
|
||||||
|
background: none repeat scroll 0 0 rgba(20, 22, 23, 0.8);
|
||||||
|
font-weight: bold;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 0.8em;
|
||||||
|
z-index: 1012;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
#umap-alert-container.error {
|
||||||
|
background-color: #c60f13;
|
||||||
|
}
|
||||||
|
.umap-alert #umap-alert-container {
|
||||||
|
visibility: visible;
|
||||||
|
top: 23px;
|
||||||
|
}
|
||||||
|
#umap-alert-container .umap-action {
|
||||||
|
margin-left: 10px;
|
||||||
|
background-color: #fff;
|
||||||
|
color: #000;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
#umap-alert-container .umap-action:hover {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
#umap-alert-container .error .umap-action {
|
||||||
|
background-color: #666;
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
#umap-alert-container .error .umap-action:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
#umap-alert-container input {
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#umap-alert-container .umap-close-link {
|
||||||
|
color: #fff;
|
||||||
|
float: right;
|
||||||
|
padding-right: 10px;
|
||||||
|
width: 100px;
|
||||||
|
line-height: 1;
|
||||||
|
margin: .5rem;
|
||||||
|
background-color: #202425;
|
||||||
|
font-size: .7rem;
|
||||||
|
}
|
||||||
|
#umap-alert-container .umap-close-icon {
|
||||||
|
background-position: -74px -55px;
|
||||||
|
}
|
||||||
|
#umap-alert-container .umap-alert-actions {
|
||||||
|
display: flex;
|
||||||
|
margin: 1rem;
|
||||||
|
}
|
||||||
|
#umap-alert-container .umap-alert-actions .umap-action {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (orientation:portrait) {
|
||||||
|
#umap-alert-container {
|
||||||
|
width: 100%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ import Browser from './browser.js'
|
||||||
import Facets from './facets.js'
|
import Facets from './facets.js'
|
||||||
import Caption from './caption.js'
|
import Caption from './caption.js'
|
||||||
import { Panel, EditPanel, FullPanel } from './panel.js'
|
import { Panel, EditPanel, FullPanel } from './panel.js'
|
||||||
|
import Alert from './ui/alert.js'
|
||||||
import * as Utils from './utils.js'
|
import * as Utils from './utils.js'
|
||||||
import { SCHEMA } from './schema.js'
|
import { SCHEMA } from './schema.js'
|
||||||
import { Request, ServerRequest, RequestError, HTTPError, NOKError } from './request.js'
|
import { Request, ServerRequest, RequestError, HTTPError, NOKError } from './request.js'
|
||||||
|
@ -21,6 +22,7 @@ window.U = {
|
||||||
Browser,
|
Browser,
|
||||||
Facets,
|
Facets,
|
||||||
Panel,
|
Panel,
|
||||||
|
Alert,
|
||||||
EditPanel,
|
EditPanel,
|
||||||
FullPanel,
|
FullPanel,
|
||||||
Utils,
|
Utils,
|
||||||
|
|
|
@ -47,14 +47,18 @@ class BaseRequest {
|
||||||
// In case of error, an alert is sent, but non 20X status are not handled
|
// In case of error, an alert is sent, but non 20X status are not handled
|
||||||
// The consumer must check the response status by hand
|
// The consumer must check the response status by hand
|
||||||
export class Request extends BaseRequest {
|
export class Request extends BaseRequest {
|
||||||
constructor(ui) {
|
constructor(alert) {
|
||||||
super()
|
super()
|
||||||
this.ui = ui
|
this.alert = alert
|
||||||
|
}
|
||||||
|
|
||||||
|
fire(name, params) {
|
||||||
|
document.body.dispatchEvent(new CustomEvent(name, params))
|
||||||
}
|
}
|
||||||
|
|
||||||
async _fetch(method, uri, headers, data) {
|
async _fetch(method, uri, headers, data) {
|
||||||
const id = Math.random()
|
const id = Math.random()
|
||||||
this.ui.fire('dataloading', { id: id })
|
this.fire('dataloading', { id: id })
|
||||||
try {
|
try {
|
||||||
const response = await BaseRequest.prototype._fetch.call(
|
const response = await BaseRequest.prototype._fetch.call(
|
||||||
this,
|
this,
|
||||||
|
@ -68,7 +72,7 @@ export class Request extends BaseRequest {
|
||||||
if (error instanceof NOKError) return this._onNOK(error)
|
if (error instanceof NOKError) return this._onNOK(error)
|
||||||
return this._onError(error)
|
return this._onError(error)
|
||||||
} finally {
|
} finally {
|
||||||
this.ui.fire('dataload', { id: id })
|
this.fire('dataload', { id: id })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +85,7 @@ export class Request extends BaseRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
_onError(error) {
|
_onError(error) {
|
||||||
this.ui.alert({ content: L._('Problem in the response'), level: 'error' })
|
this.alert.open({ content: L._('Problem in the response'), level: 'error' })
|
||||||
}
|
}
|
||||||
|
|
||||||
_onNOK(error) {
|
_onNOK(error) {
|
||||||
|
@ -127,9 +131,9 @@ export class ServerRequest extends Request {
|
||||||
try {
|
try {
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
if (data.info) {
|
if (data.info) {
|
||||||
this.ui.alert({ content: data.info, level: 'info' })
|
this.alert.open({ content: data.info, level: 'info' })
|
||||||
} else if (data.error) {
|
} else if (data.error) {
|
||||||
this.ui.alert({ content: data.error, level: 'error' })
|
this.alert.open({ content: data.error, level: 'error' })
|
||||||
return this._onError(new Error(data.error))
|
return this._onError(new Error(data.error))
|
||||||
}
|
}
|
||||||
return [data, response, null]
|
return [data, response, null]
|
||||||
|
@ -144,7 +148,7 @@ export class ServerRequest extends Request {
|
||||||
|
|
||||||
_onNOK(error) {
|
_onNOK(error) {
|
||||||
if (error.status === 403) {
|
if (error.status === 403) {
|
||||||
this.ui.alert({
|
this.alert.open({
|
||||||
content: error.message || L._('Action not allowed :('),
|
content: error.message || L._('Action not allowed :('),
|
||||||
level: 'error',
|
level: 'error',
|
||||||
})
|
})
|
||||||
|
|
82
umap/static/umap/js/modules/ui/alert.js
Normal file
82
umap/static/umap/js/modules/ui/alert.js
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
import { DomUtil, DomEvent } from '../../../vendors/leaflet/leaflet-src.esm.js'
|
||||||
|
import { translate } from '../i18n.js'
|
||||||
|
|
||||||
|
const ALERTS = []
|
||||||
|
let ALERT_ID = null
|
||||||
|
|
||||||
|
export default class Alert {
|
||||||
|
constructor(parent) {
|
||||||
|
this.parent = parent
|
||||||
|
this.container = DomUtil.create('div', 'with-transition', this.parent)
|
||||||
|
this.container.id = 'umap-alert-container'
|
||||||
|
DomEvent.disableClickPropagation(this.container)
|
||||||
|
DomEvent.on(this.container, 'contextmenu', DomEvent.stopPropagation) // Do not activate our custom context menu.
|
||||||
|
DomEvent.on(this.container, 'wheel', DomEvent.stopPropagation)
|
||||||
|
DomEvent.on(this.container, 'MozMousePixelScroll', DomEvent.stopPropagation)
|
||||||
|
}
|
||||||
|
|
||||||
|
open(params) {
|
||||||
|
if (DomUtil.hasClass(this.parent, 'umap-alert')) ALERTS.push(params)
|
||||||
|
else this._open(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
_open(params) {
|
||||||
|
if (!params) {
|
||||||
|
if (ALERTS.length) params = ALERTS.pop()
|
||||||
|
else return
|
||||||
|
}
|
||||||
|
let timeoutID
|
||||||
|
const level_class = params.level && params.level == 'info' ? 'info' : 'error'
|
||||||
|
this.container.innerHTML = ''
|
||||||
|
DomUtil.addClass(this.parent, 'umap-alert')
|
||||||
|
DomUtil.addClass(this.container, level_class)
|
||||||
|
const close = () => {
|
||||||
|
if (timeoutID && timeoutID !== ALERT_ID) {
|
||||||
|
return
|
||||||
|
} // Another alert has been forced
|
||||||
|
this.container.innerHTML = ''
|
||||||
|
DomUtil.removeClass(this.parent, 'umap-alert')
|
||||||
|
DomUtil.removeClass(this.container, level_class)
|
||||||
|
if (timeoutID) window.clearTimeout(timeoutID)
|
||||||
|
this._open()
|
||||||
|
}
|
||||||
|
const closeButton = DomUtil.createButton(
|
||||||
|
'umap-close-link',
|
||||||
|
this.container,
|
||||||
|
'',
|
||||||
|
close,
|
||||||
|
this
|
||||||
|
)
|
||||||
|
DomUtil.create('i', 'umap-close-icon', closeButton)
|
||||||
|
const label = DomUtil.create('span', '', closeButton)
|
||||||
|
label.title = label.textContent = translate('Close')
|
||||||
|
DomUtil.element({
|
||||||
|
tagName: 'div',
|
||||||
|
innerHTML: params.content,
|
||||||
|
parent: this.container,
|
||||||
|
})
|
||||||
|
let action, el, input
|
||||||
|
const form = DomUtil.create('div', 'umap-alert-actions', this.container)
|
||||||
|
for (let action of params.actions || []) {
|
||||||
|
if (action.input) {
|
||||||
|
input = DomUtil.element({
|
||||||
|
tagName: 'input',
|
||||||
|
parent: form,
|
||||||
|
className: 'umap-alert-input',
|
||||||
|
placeholder: action.input,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
el = DomUtil.createButton(
|
||||||
|
'umap-action',
|
||||||
|
form,
|
||||||
|
action.label,
|
||||||
|
action.callback,
|
||||||
|
action.callbackContext
|
||||||
|
)
|
||||||
|
DomEvent.on(el, 'click', close, this)
|
||||||
|
}
|
||||||
|
if (params.duration !== Infinity) {
|
||||||
|
ALERT_ID = timeoutID = window.setTimeout(close, params.duration || 3000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,8 +12,8 @@ U.AutoComplete = L.Class.extend({
|
||||||
|
|
||||||
initialize: function (el, options) {
|
initialize: function (el, options) {
|
||||||
this.el = el
|
this.el = el
|
||||||
const ui = new U.UI(document.querySelector('header'))
|
const alert = new U.Alert(document.querySelector('header'))
|
||||||
this.server = new U.ServerRequest(ui)
|
this.server = new U.ServerRequest(alert)
|
||||||
L.setOptions(this, options)
|
L.setOptions(this, options)
|
||||||
let CURRENT = null
|
let CURRENT = null
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1048,7 +1048,6 @@ U.Locate = L.Control.Locate.extend({
|
||||||
if (!this._container || !this._container.parentNode) return
|
if (!this._container || !this._container.parentNode) return
|
||||||
return L.Control.Locate.prototype.remove.call(this)
|
return L.Control.Locate.prototype.remove.call(this)
|
||||||
},
|
},
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
U.Search = L.PhotonSearch.extend({
|
U.Search = L.PhotonSearch.extend({
|
||||||
|
@ -1087,7 +1086,7 @@ U.Search = L.PhotonSearch.extend({
|
||||||
if (latlng.isValid()) {
|
if (latlng.isValid()) {
|
||||||
this.reverse.doReverse(latlng)
|
this.reverse.doReverse(latlng)
|
||||||
} else {
|
} else {
|
||||||
this.map.ui.alert({ content: 'Invalid latitude or longitude', mode: 'error' })
|
this.map.alert.open({ content: 'Invalid latitude or longitude', mode: 'error' })
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -726,7 +726,7 @@ U.Marker = L.Marker.extend({
|
||||||
const builder = new U.FormBuilder(this, coordinatesOptions, {
|
const builder = new U.FormBuilder(this, coordinatesOptions, {
|
||||||
callback: function () {
|
callback: function () {
|
||||||
if (!this._latlng.isValid()) {
|
if (!this._latlng.isValid()) {
|
||||||
this.map.ui.alert({
|
this.map.alert.open({
|
||||||
content: L._('Invalid latitude or longitude'),
|
content: L._('Invalid latitude or longitude'),
|
||||||
level: 'error',
|
level: 'error',
|
||||||
})
|
})
|
||||||
|
@ -928,7 +928,7 @@ U.PathMixin = {
|
||||||
items.push({
|
items.push({
|
||||||
text: L._('Display measure'),
|
text: L._('Display measure'),
|
||||||
callback: function () {
|
callback: function () {
|
||||||
this.map.ui.alert({ content: this.getMeasure(), level: 'info' })
|
this.map.alert.open({ content: this.getMeasure(), level: 'info' })
|
||||||
},
|
},
|
||||||
context: this,
|
context: this,
|
||||||
})
|
})
|
||||||
|
|
|
@ -161,7 +161,7 @@ U.Importer = L.Class.extend({
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!type)
|
if (!type)
|
||||||
return this.map.ui.alert({
|
return this.map.alert.open({
|
||||||
content: L._('Please choose a format'),
|
content: L._('Please choose a format'),
|
||||||
level: 'error',
|
level: 'error',
|
||||||
})
|
})
|
||||||
|
@ -169,7 +169,7 @@ U.Importer = L.Class.extend({
|
||||||
try {
|
try {
|
||||||
this.map.importRaw(this.rawInput.value, type)
|
this.map.importRaw(this.rawInput.value, type)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.ui.alert({ content: L._('Invalid umap data'), level: 'error' })
|
this.alert.open({ content: L._('Invalid umap data'), level: 'error' })
|
||||||
console.error(e)
|
console.error(e)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -57,15 +57,16 @@ U.Map = L.Map.extend({
|
||||||
this.urls = new U.URLs(this.options.urls)
|
this.urls = new U.URLs(this.options.urls)
|
||||||
|
|
||||||
this.panel = new U.Panel(this)
|
this.panel = new U.Panel(this)
|
||||||
|
this.alert = new U.Alert(this._controlContainer)
|
||||||
if (this.hasEditMode()) {
|
if (this.hasEditMode()) {
|
||||||
this.editPanel = new U.EditPanel(this)
|
this.editPanel = new U.EditPanel(this)
|
||||||
this.fullPanel = new U.FullPanel(this)
|
this.fullPanel = new U.FullPanel(this)
|
||||||
}
|
}
|
||||||
this.ui = new U.UI(this._container)
|
this.ui = new U.UI(this._container)
|
||||||
this.ui.on('dataloading', (e) => this.fire('dataloading', e))
|
L.DomEvent.on(document.body, 'dataloading', (e) => this.fire('dataloading', e))
|
||||||
this.ui.on('dataload', (e) => this.fire('dataload', e))
|
L.DomEvent.on(document.body, 'dataload', (e) => this.fire('dataload', e))
|
||||||
this.server = new U.ServerRequest(this.ui)
|
this.server = new U.ServerRequest(this.alert)
|
||||||
this.request = new U.Request(this.ui)
|
this.request = new U.Request(this.alert)
|
||||||
|
|
||||||
this.initLoader()
|
this.initLoader()
|
||||||
this.name = this.options.name
|
this.name = this.options.name
|
||||||
|
@ -359,7 +360,7 @@ U.Map = L.Map.extend({
|
||||||
icon: 'umap-fake-class',
|
icon: 'umap-fake-class',
|
||||||
iconLoading: 'umap-fake-class',
|
iconLoading: 'umap-fake-class',
|
||||||
flyTo: this.options.easing,
|
flyTo: this.options.easing,
|
||||||
onLocationError: (err) => this.ui.alert({ content: err.message }),
|
onLocationError: (err) => this.alert.open({ content: err.message }),
|
||||||
})
|
})
|
||||||
this._controls.fullscreen = new L.Control.Fullscreen({
|
this._controls.fullscreen = new L.Control.Fullscreen({
|
||||||
title: { false: L._('View Fullscreen'), true: L._('Exit Fullscreen') },
|
title: { false: L._('View Fullscreen'), true: L._('Exit Fullscreen') },
|
||||||
|
@ -392,7 +393,9 @@ U.Map = L.Map.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
renderControls: function () {
|
renderControls: function () {
|
||||||
const hasSlideshow = Boolean(this.options.slideshow && this.options.slideshow.active)
|
const hasSlideshow = Boolean(
|
||||||
|
this.options.slideshow && this.options.slideshow.active
|
||||||
|
)
|
||||||
const barEnabled = this.options.captionBar || hasSlideshow
|
const barEnabled = this.options.captionBar || hasSlideshow
|
||||||
document.body.classList.toggle('umap-caption-bar-enabled', barEnabled)
|
document.body.classList.toggle('umap-caption-bar-enabled', barEnabled)
|
||||||
document.body.classList.toggle('umap-slideshow-enabled', hasSlideshow)
|
document.body.classList.toggle('umap-slideshow-enabled', hasSlideshow)
|
||||||
|
@ -641,7 +644,7 @@ U.Map = L.Map.extend({
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
this.removeLayer(tilelayer)
|
this.removeLayer(tilelayer)
|
||||||
this.ui.alert({
|
this.alert.open({
|
||||||
content: `${L._('Error in the tilelayer URL')}: ${tilelayer._url}`,
|
content: `${L._('Error in the tilelayer URL')}: ${tilelayer._url}`,
|
||||||
level: 'error',
|
level: 'error',
|
||||||
})
|
})
|
||||||
|
@ -676,7 +679,7 @@ U.Map = L.Map.extend({
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.removeLayer(overlay)
|
this.removeLayer(overlay)
|
||||||
console.error(e)
|
console.error(e)
|
||||||
this.ui.alert({
|
this.alert.open({
|
||||||
content: `${L._('Error in the overlay URL')}: ${overlay._url}`,
|
content: `${L._('Error in the overlay URL')}: ${overlay._url}`,
|
||||||
level: 'error',
|
level: 'error',
|
||||||
})
|
})
|
||||||
|
@ -799,7 +802,7 @@ U.Map = L.Map.extend({
|
||||||
if (this.options.umap_id) {
|
if (this.options.umap_id) {
|
||||||
// We do not want an extra message during the map creation
|
// We do not want an extra message during the map creation
|
||||||
// to avoid the double notification/alert.
|
// to avoid the double notification/alert.
|
||||||
this.ui.alert({
|
this.alert.open({
|
||||||
content: L._('The zoom and center have been modified.'),
|
content: L._('The zoom and center have been modified.'),
|
||||||
level: 'info',
|
level: 'info',
|
||||||
})
|
})
|
||||||
|
@ -842,7 +845,7 @@ U.Map = L.Map.extend({
|
||||||
processFileToImport: function (file, layer, type) {
|
processFileToImport: function (file, layer, type) {
|
||||||
type = type || U.Utils.detectFileType(file)
|
type = type || U.Utils.detectFileType(file)
|
||||||
if (!type) {
|
if (!type) {
|
||||||
this.ui.alert({
|
this.alert.open({
|
||||||
content: L._('Unable to detect format of file {filename}', {
|
content: L._('Unable to detect format of file {filename}', {
|
||||||
filename: file.name,
|
filename: file.name,
|
||||||
}),
|
}),
|
||||||
|
@ -899,7 +902,7 @@ U.Map = L.Map.extend({
|
||||||
self.importRaw(rawData)
|
self.importRaw(rawData)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error importing data', e)
|
console.error('Error importing data', e)
|
||||||
self.ui.alert({
|
self.alert.open({
|
||||||
content: L._('Invalid umap data in {filename}', { filename: file.name }),
|
content: L._('Invalid umap data in {filename}', { filename: file.name }),
|
||||||
level: 'error',
|
level: 'error',
|
||||||
})
|
})
|
||||||
|
@ -1030,7 +1033,7 @@ U.Map = L.Map.extend({
|
||||||
label: L._('Copy link'),
|
label: L._('Copy link'),
|
||||||
callback: () => {
|
callback: () => {
|
||||||
L.Util.copyToClipboard(data.permissions.anonymous_edit_url)
|
L.Util.copyToClipboard(data.permissions.anonymous_edit_url)
|
||||||
this.ui.alert({
|
this.alert.open({
|
||||||
content: L._('Secret edit link copied to clipboard!'),
|
content: L._('Secret edit link copied to clipboard!'),
|
||||||
level: 'info',
|
level: 'info',
|
||||||
})
|
})
|
||||||
|
@ -1058,7 +1061,7 @@ U.Map = L.Map.extend({
|
||||||
history.pushState({}, this.options.name, data.url)
|
history.pushState({}, this.options.name, data.url)
|
||||||
else window.location = data.url
|
else window.location = data.url
|
||||||
alert.content = data.info || alert.content
|
alert.content = data.info || alert.content
|
||||||
this.once('saved', () => this.ui.alert(alert))
|
this.once('saved', () => this.alert.open(alert))
|
||||||
this.permissions.save()
|
this.permissions.save()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1079,7 +1082,7 @@ U.Map = L.Map.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
sendEditLink: async function () {
|
sendEditLink: async function () {
|
||||||
const input = this.ui._alert.querySelector('input')
|
const input = this.alert.container.querySelector('input')
|
||||||
const email = input.value
|
const email = input.value
|
||||||
|
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
|
@ -1091,7 +1094,7 @@ U.Map = L.Map.extend({
|
||||||
|
|
||||||
star: async function () {
|
star: async function () {
|
||||||
if (!this.options.umap_id)
|
if (!this.options.umap_id)
|
||||||
return this.ui.alert({
|
return this.alert.open({
|
||||||
content: L._('Please save the map first'),
|
content: L._('Please save the map first'),
|
||||||
level: 'error',
|
level: 'error',
|
||||||
})
|
})
|
||||||
|
@ -1102,7 +1105,7 @@ U.Map = L.Map.extend({
|
||||||
let msg = data.starred
|
let msg = data.starred
|
||||||
? L._('Map has been starred')
|
? L._('Map has been starred')
|
||||||
: L._('Map has been unstarred')
|
: L._('Map has been unstarred')
|
||||||
this.ui.alert({ content: msg, level: 'info' })
|
this.alert.open({ content: msg, level: 'info' })
|
||||||
this.renderControls()
|
this.renderControls()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -965,7 +965,7 @@ U.DataLayer = L.Evented.extend({
|
||||||
message: err[0].message,
|
message: err[0].message,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.map.ui.alert({ content: message, level: 'error', duration: 10000 })
|
this.map.alert.open({ content: message, level: 'error', duration: 10000 })
|
||||||
console.error(err)
|
console.error(err)
|
||||||
}
|
}
|
||||||
if (result && result.features.length) {
|
if (result && result.features.length) {
|
||||||
|
@ -992,7 +992,7 @@ U.DataLayer = L.Evented.extend({
|
||||||
const gj = JSON.parse(c)
|
const gj = JSON.parse(c)
|
||||||
callback(gj)
|
callback(gj)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.map.ui.alert({ content: `Invalid JSON file: ${err}` })
|
this.map.alert.open({ content: `Invalid JSON file: ${err}` })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1050,7 +1050,7 @@ U.DataLayer = L.Evented.extend({
|
||||||
return this.geojsonToFeatures(geometry.geometries)
|
return this.geojsonToFeatures(geometry.geometries)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
this.map.ui.alert({
|
this.map.alert.open({
|
||||||
content: L._('Skipping unknown geometry.type: {type}', {
|
content: L._('Skipping unknown geometry.type: {type}', {
|
||||||
type: geometry.type || 'undefined',
|
type: geometry.type || 'undefined',
|
||||||
}),
|
}),
|
||||||
|
@ -1641,7 +1641,7 @@ U.DataLayer = L.Evented.extend({
|
||||||
label: L._('Cancel'),
|
label: L._('Cancel'),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
this.map.ui.alert({
|
this.map.alert.open({
|
||||||
content: msg,
|
content: msg,
|
||||||
level: 'error',
|
level: 'error',
|
||||||
duration: 100000,
|
duration: 100000,
|
||||||
|
|
|
@ -53,7 +53,7 @@ U.MapPermissions = L.Class.extend({
|
||||||
edit: function () {
|
edit: function () {
|
||||||
if (this.map.options.editMode !== 'advanced') return
|
if (this.map.options.editMode !== 'advanced') return
|
||||||
if (!this.map.options.umap_id)
|
if (!this.map.options.umap_id)
|
||||||
return this.map.ui.alert({
|
return this.map.alert.open({
|
||||||
content: L._('Please save the map first'),
|
content: L._('Please save the map first'),
|
||||||
level: 'info',
|
level: 'info',
|
||||||
})
|
})
|
||||||
|
@ -139,7 +139,7 @@ U.MapPermissions = L.Class.extend({
|
||||||
const [data, response, error] = await this.map.server.post(this.getAttachUrl())
|
const [data, response, error] = await this.map.server.post(this.getAttachUrl())
|
||||||
if (!error) {
|
if (!error) {
|
||||||
this.options.owner = this.map.options.user
|
this.options.owner = this.map.options.user
|
||||||
this.map.ui.alert({
|
this.map.alert.open({
|
||||||
content: L._('Map has been attached to your account'),
|
content: L._('Map has been attached to your account'),
|
||||||
level: 'info',
|
level: 'info',
|
||||||
})
|
})
|
||||||
|
|
|
@ -83,7 +83,7 @@ U.TableEditor = L.Class.extend({
|
||||||
|
|
||||||
validateName: function (name) {
|
validateName: function (name) {
|
||||||
if (name.indexOf('.') !== -1) {
|
if (name.indexOf('.') !== -1) {
|
||||||
this.datalayer.map.ui.alert({
|
this.datalayer.map.alert.open({
|
||||||
content: L._('Invalide property name: {name}', { name: name }),
|
content: L._('Invalide property name: {name}', { name: name }),
|
||||||
level: 'error',
|
level: 'error',
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
* Modals
|
* Modals
|
||||||
*/
|
*/
|
||||||
U.UI = L.Evented.extend({
|
U.UI = L.Evented.extend({
|
||||||
ALERTS: Array(),
|
|
||||||
ALERT_ID: null,
|
|
||||||
TOOLTIP_ID: null,
|
TOOLTIP_ID: null,
|
||||||
|
|
||||||
initialize: function (parent) {
|
initialize: function (parent) {
|
||||||
|
@ -13,79 +11,10 @@ U.UI = L.Evented.extend({
|
||||||
L.DomEvent.on(this.container, 'contextmenu', L.DomEvent.stopPropagation) // Do not activate our custom context menu.
|
L.DomEvent.on(this.container, 'contextmenu', L.DomEvent.stopPropagation) // Do not activate our custom context menu.
|
||||||
L.DomEvent.on(this.container, 'wheel', L.DomEvent.stopPropagation)
|
L.DomEvent.on(this.container, 'wheel', L.DomEvent.stopPropagation)
|
||||||
L.DomEvent.on(this.container, 'MozMousePixelScroll', L.DomEvent.stopPropagation)
|
L.DomEvent.on(this.container, 'MozMousePixelScroll', L.DomEvent.stopPropagation)
|
||||||
this._alert = L.DomUtil.create('div', 'with-transition', this.container)
|
|
||||||
this._alert.id = 'umap-alert-container'
|
|
||||||
this._tooltip = L.DomUtil.create('div', '', this.container)
|
this._tooltip = L.DomUtil.create('div', '', this.container)
|
||||||
this._tooltip.id = 'umap-tooltip-container'
|
this._tooltip.id = 'umap-tooltip-container'
|
||||||
},
|
},
|
||||||
|
|
||||||
alert: function (e) {
|
|
||||||
if (L.DomUtil.hasClass(this.parent, 'umap-alert')) this.ALERTS.push(e)
|
|
||||||
else this.popAlert(e)
|
|
||||||
},
|
|
||||||
|
|
||||||
popAlert: function (e) {
|
|
||||||
if (!e) {
|
|
||||||
if (this.ALERTS.length) e = this.ALERTS.pop()
|
|
||||||
else return
|
|
||||||
}
|
|
||||||
let timeoutID
|
|
||||||
const level_class = e.level && e.level == 'info' ? 'info' : 'error'
|
|
||||||
this._alert.innerHTML = ''
|
|
||||||
L.DomUtil.addClass(this.parent, 'umap-alert')
|
|
||||||
L.DomUtil.addClass(this._alert, level_class)
|
|
||||||
const close = () => {
|
|
||||||
if (timeoutID && timeoutID !== this.ALERT_ID) {
|
|
||||||
return
|
|
||||||
} // Another alert has been forced
|
|
||||||
this._alert.innerHTML = ''
|
|
||||||
L.DomUtil.removeClass(this.parent, 'umap-alert')
|
|
||||||
L.DomUtil.removeClass(this._alert, level_class)
|
|
||||||
if (timeoutID) window.clearTimeout(timeoutID)
|
|
||||||
this.popAlert()
|
|
||||||
}
|
|
||||||
const closeButton = L.DomUtil.createButton(
|
|
||||||
'umap-close-link',
|
|
||||||
this._alert,
|
|
||||||
'',
|
|
||||||
close,
|
|
||||||
this
|
|
||||||
)
|
|
||||||
L.DomUtil.create('i', 'umap-close-icon', closeButton)
|
|
||||||
const label = L.DomUtil.create('span', '', closeButton)
|
|
||||||
label.title = label.textContent = L._('Close')
|
|
||||||
L.DomUtil.element({ tagName: 'div', innerHTML: e.content, parent: this._alert })
|
|
||||||
if (e.actions) {
|
|
||||||
let action, el, input
|
|
||||||
const form = L.DomUtil.create('div', 'umap-alert-actions', this._alert)
|
|
||||||
for (let i = 0; i < e.actions.length; i++) {
|
|
||||||
action = e.actions[i]
|
|
||||||
if (action.input) {
|
|
||||||
input = L.DomUtil.element({
|
|
||||||
tagName: 'input',
|
|
||||||
parent: form,
|
|
||||||
className: 'umap-alert-input',
|
|
||||||
placeholder: action.input,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
el = L.DomUtil.createButton(
|
|
||||||
'umap-action',
|
|
||||||
form,
|
|
||||||
action.label,
|
|
||||||
action.callback,
|
|
||||||
action.callbackContext || this.map
|
|
||||||
)
|
|
||||||
L.DomEvent.on(el, 'click', close, this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (e.duration !== Infinity) {
|
|
||||||
this.ALERT_ID = timeoutID = window.setTimeout(
|
|
||||||
L.bind(close, this),
|
|
||||||
e.duration || 3000
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
tooltip: function (opts) {
|
tooltip: function (opts) {
|
||||||
function showIt() {
|
function showIt() {
|
||||||
if (opts.anchor && opts.position === 'top') {
|
if (opts.anchor && opts.position === 'top') {
|
||||||
|
|
|
@ -38,8 +38,8 @@
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window.addEventListener('DOMContentLoaded', event => {
|
window.addEventListener('DOMContentLoaded', event => {
|
||||||
const ui = new U.UI(document.querySelector('header'))
|
const alert = new U.Alert(document.querySelector('header'))
|
||||||
const server = new U.ServerRequest(ui)
|
const server = new U.ServerRequest(alert)
|
||||||
const getMore = async function (e) {
|
const getMore = async function (e) {
|
||||||
L.DomEvent.stop(e)
|
L.DomEvent.stop(e)
|
||||||
const [{html}, response, error] = await server.get(this.href)
|
const [{html}, response, error] = await server.get(this.href)
|
||||||
|
|
|
@ -29,4 +29,5 @@
|
||||||
<link rel="stylesheet" href="{% static 'umap/nav.css' %}" />
|
<link rel="stylesheet" href="{% static 'umap/nav.css' %}" />
|
||||||
<link rel="stylesheet" href="{% static 'umap/map.css' %}" />
|
<link rel="stylesheet" href="{% static 'umap/map.css' %}" />
|
||||||
<link rel="stylesheet" href="{% static 'umap/css/panel.css' %}" />
|
<link rel="stylesheet" href="{% static 'umap/css/panel.css' %}" />
|
||||||
|
<link rel="stylesheet" href="{% static 'umap/css/alert.css' %}" />
|
||||||
<link rel="stylesheet" href="{% static 'umap/theme.css' %}" />
|
<link rel="stylesheet" href="{% static 'umap/theme.css' %}" />
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
U.MAP = new U.Map("map", {{ map_settings|notag|safe }})
|
U.MAP = new U.Map("map", {{ map_settings|notag|safe }})
|
||||||
{% for m in messages %}
|
{% for m in messages %}
|
||||||
{# We have just one, but we need to loop, as for messages API #}
|
{# We have just one, but we need to loop, as for messages API #}
|
||||||
U.MAP.ui.alert({
|
U.MAP.alert.open({
|
||||||
content: "{{ m }}",
|
content: "{{ m }}",
|
||||||
level: "{{ m.tags }}",
|
level: "{{ m.tags }}",
|
||||||
duration: 100000
|
duration: 100000
|
||||||
|
|
|
@ -164,7 +164,7 @@ def test_alert_message_after_create(
|
||||||
page.goto(f"{live_server.url}/en/map/new")
|
page.goto(f"{live_server.url}/en/map/new")
|
||||||
save = page.get_by_role("button", name="Save")
|
save = page.get_by_role("button", name="Save")
|
||||||
expect(save).to_be_visible()
|
expect(save).to_be_visible()
|
||||||
alert = page.locator(".umap-alert")
|
alert = page.locator("#umap-alert-container")
|
||||||
expect(alert).to_be_hidden()
|
expect(alert).to_be_hidden()
|
||||||
with page.expect_response(re.compile(r".*/map/create/")):
|
with page.expect_response(re.compile(r".*/map/create/")):
|
||||||
save.click()
|
save.click()
|
||||||
|
@ -194,7 +194,7 @@ def test_alert_message_after_create(
|
||||||
|
|
||||||
def test_email_sending_error_are_catched(tilelayer, page, live_server):
|
def test_email_sending_error_are_catched(tilelayer, page, live_server):
|
||||||
page.goto(f"{live_server.url}/en/map/new")
|
page.goto(f"{live_server.url}/en/map/new")
|
||||||
alert = page.locator(".umap-alert")
|
alert = page.locator("#umap-alert-container")
|
||||||
with page.expect_response(re.compile(r".*/map/create/")):
|
with page.expect_response(re.compile(r".*/map/create/")):
|
||||||
page.get_by_role("button", name="Save").click()
|
page.get_by_role("button", name="Save").click()
|
||||||
alert.get_by_placeholder("Email").fill("foo@bar.com")
|
alert.get_by_placeholder("Email").fill("foo@bar.com")
|
||||||
|
@ -214,7 +214,7 @@ def test_alert_message_after_create_show_link_even_without_mail(
|
||||||
page.goto(f"{live_server.url}/en/map/new")
|
page.goto(f"{live_server.url}/en/map/new")
|
||||||
with page.expect_response(re.compile(r".*/map/create/")):
|
with page.expect_response(re.compile(r".*/map/create/")):
|
||||||
page.get_by_role("button", name="Save").click()
|
page.get_by_role("button", name="Save").click()
|
||||||
alert = page.locator(".umap-alert")
|
alert = page.locator("#umap-alert-container")
|
||||||
expect(alert).to_be_visible()
|
expect(alert).to_be_visible()
|
||||||
expect(
|
expect(
|
||||||
alert.get_by_text(
|
alert.get_by_text(
|
||||||
|
|
|
@ -448,4 +448,4 @@ def test_import_csv_without_valid_latlon_headers(tilelayer, live_server, page):
|
||||||
# FIXME do not create a layer
|
# FIXME do not create a layer
|
||||||
expect(layers).to_have_count(1)
|
expect(layers).to_have_count(1)
|
||||||
expect(markers).to_have_count(0)
|
expect(markers).to_have_count(0)
|
||||||
expect(page.locator(".umap-alert")).to_be_visible()
|
expect(page.locator("#umap-alert-container")).to_be_visible()
|
||||||
|
|
Loading…
Reference in a new issue