mirror of
https://github.com/umap-project/umap.git
synced 2025-04-28 19:42:36 +02:00
chore: move editToolBar and captionBar to modules
This also tries to rework a bit the "reflow" process, which how to edit the UI when something changes in the data. The idea is to build the whole HTML, then: - the `propagate` method tries to change the UI with targetted CSS selector, but anywhere - while `render` hide/show some elements This is not the destination, but just another step. We certainly need to refactor the SCHEMA to make the next step (as we want to associate some data change to UI change).
This commit is contained in:
parent
2c64745c52
commit
5ceda7b2a3
11 changed files with 514 additions and 489 deletions
233
umap/static/umap/css/bar.css
Normal file
233
umap/static/umap/css/bar.css
Normal file
|
@ -0,0 +1,233 @@
|
|||
.umap-main-edit-toolbox [type="button"] {
|
||||
color: #fff;
|
||||
font-size: 1.2em;
|
||||
border: none;
|
||||
background-color: var(--color-darkGray);
|
||||
width: auto;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.umap-main-edit-toolbox [type="button"]:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.leaflet-container [type="button"].umap-help-link {
|
||||
font-size: 12px;
|
||||
padding-bottom: 3px;
|
||||
background-color: inherit;
|
||||
}
|
||||
.leaflet-container .edit-save,
|
||||
.leaflet-container .edit-cancel,
|
||||
.leaflet-container .edit-disable,
|
||||
.leaflet-container .connected-peers
|
||||
{
|
||||
display: block;
|
||||
border: none;
|
||||
font-size: 12px;
|
||||
border-radius: 20px;
|
||||
color: #f8f8f8;
|
||||
height: 32px;
|
||||
line-height: 30px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.leaflet-container .connected-peers,
|
||||
.dark [type="button"].connected-peers:hover
|
||||
{
|
||||
background-color: var(--color-lightCyan);
|
||||
color: var(--color-dark);
|
||||
}
|
||||
|
||||
.leaflet-container .edit-disable:before,
|
||||
.leaflet-container .edit-save:before,
|
||||
.leaflet-container .edit-cancel:before,
|
||||
.leaflet-container .connected-peers:before {
|
||||
display: inline-block;
|
||||
width: 19px;
|
||||
height: 24px;
|
||||
background-position: -50px -122px;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url('../img/16-white.svg');
|
||||
vertical-align: middle;
|
||||
content: ' ';
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.leaflet-container .connected-peers:before {
|
||||
background-image: url('../img/16.svg');
|
||||
}
|
||||
|
||||
.leaflet-container .edit-disable span,
|
||||
.leaflet-container .edit-save span,
|
||||
.leaflet-container .edit-cancel span,
|
||||
.leaflet-container .connected-peers span{
|
||||
margin-inline-start: 10px;
|
||||
}
|
||||
.leaflet-container .edit-save:before {
|
||||
background-position: -148px -2px;
|
||||
}
|
||||
.leaflet-container .edit-disable:before {
|
||||
background-position: -50px -25px;
|
||||
}
|
||||
.leaflet-container .connected-peers:before {
|
||||
background-position: -2px -95px;
|
||||
}
|
||||
.leaflet-container .edit-cancel,
|
||||
.leaflet-container .edit-disable,
|
||||
.leaflet-container .connected-peers{
|
||||
border: 0.5px solid rgba(153, 153, 153, 0.40);
|
||||
}
|
||||
.leaflet-container .edit-cancel:hover,
|
||||
.leaflet-container .edit-disable:hover {
|
||||
border: 0.5px solid rgba(153, 153, 153, 0.80);
|
||||
text-decoration: none;
|
||||
}
|
||||
.leaflet-container .edit-save {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
border-radius: 16px;
|
||||
border: 0.5px solid rgba(153, 153, 153, 0.40);
|
||||
background: rgba(153, 153, 153, 0.10);
|
||||
}
|
||||
.dark [type="button"].edit-save:hover {
|
||||
background: rgba(153, 153, 153, 0.10);
|
||||
text-decoration: none;
|
||||
}
|
||||
.umap-is-dirty .edit-save {
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
border: 0.5px solid rgba(66, 236, 230, 0.40);
|
||||
background: rgba(66, 236, 230, 0.10);
|
||||
color: #42ECE6;
|
||||
}
|
||||
.umap-is-dirty .edit-save:before {
|
||||
background-position: -148px -26px;
|
||||
}
|
||||
.umap-is-dirty .dark [type="button"].edit-save:hover {
|
||||
border-color: rgba(66, 236, 230, 0.80);
|
||||
background: rgba(66, 236, 230, 0.10);
|
||||
}
|
||||
.leaflet-container .edit-save,
|
||||
.leaflet-container .edit-cancel,
|
||||
.leaflet-container .edit-disable,
|
||||
.umap-edit-enabled .edit-enable {
|
||||
display: none;
|
||||
}
|
||||
.umap-edit-enabled .edit-save,
|
||||
.umap-edit-enabled .edit-disable,
|
||||
.umap-edit-enabled.umap-is-dirty .edit-cancel {
|
||||
display: inline-block;
|
||||
}
|
||||
.umap-is-dirty .edit-disable {
|
||||
display: none;
|
||||
}
|
||||
.umap-caption-bar {
|
||||
display: none;
|
||||
}
|
||||
.umap-main-edit-toolbox {
|
||||
top: -46px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 46px;
|
||||
padding: 0 10px;
|
||||
text-align: start;
|
||||
line-height: var(--control-size);
|
||||
cursor: auto;
|
||||
border-bottom: 1px solid #222;
|
||||
z-index: var(--zindex-panels);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
}
|
||||
.umap-left-edit-toolbox,
|
||||
.umap-right-edit-toolbox {
|
||||
display: flex;
|
||||
column-gap: 10px;
|
||||
}
|
||||
.umap-right-edit-toolbox {
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.umap-main-edit-toolbox .logo {
|
||||
width: 39px;
|
||||
height: 100%;
|
||||
}
|
||||
.umap-main-edit-toolbox .logo a {
|
||||
background-image: url('../img/logo_small.svg');
|
||||
background-position: 0 center;
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
width: 39px;
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
text-indent: -9999px;
|
||||
}
|
||||
.umap-main-edit-toolbox .map-name {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
font-weight: bold;
|
||||
text-align: start;
|
||||
}
|
||||
.umap-main-edit-toolbox .share-status {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.map-name:after {
|
||||
content: '\00a0';
|
||||
padding-inline-start: 3px;
|
||||
width: 1ch;
|
||||
display: inline-block;
|
||||
}
|
||||
.umap-is-dirty .map-name:after {
|
||||
content: '*';
|
||||
}
|
||||
.umap-edit-enabled .umap-main-edit-toolbox {
|
||||
top: 0;
|
||||
}
|
||||
.umap-caption-bar h3,
|
||||
.umap-main-edit-toolbox h3 {
|
||||
display: inline;
|
||||
}
|
||||
.umap-caption-bar button {
|
||||
margin-inline-start: 10px;
|
||||
}
|
||||
.umap-caption-bar button + button:before {
|
||||
content: '|';
|
||||
padding-inline-end: 10px;
|
||||
}
|
||||
.umap-main-edit-toolbox .umap-user {
|
||||
color: #fff;
|
||||
}
|
||||
.umap-main-edit-toolbox .umap-user:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.umap-main-edit-toolbox .umap-user:after {
|
||||
content: '|';
|
||||
padding-inline-start: 20px;
|
||||
display: inline-block; /* Prevents underline on hover. */
|
||||
}
|
||||
.umap-caption-bar-enabled .umap-caption-bar {
|
||||
display: block;
|
||||
height: var(--footer-height);
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding: var(--gutter);
|
||||
text-align: start;
|
||||
line-height: 100%;
|
||||
cursor: auto;
|
||||
border-top: 1px solid var(--color-lightGray);
|
||||
opacity: 0.93;
|
||||
z-index: var(--zindex-panels);
|
||||
}
|
||||
.umap-caption-bar-enabled {
|
||||
--current-footer-height: var(--footer-height);
|
||||
}
|
|
@ -226,13 +226,6 @@ export default class Help {
|
|||
return button
|
||||
}
|
||||
|
||||
getStartedLink(container) {
|
||||
const button = DomUtil.createButton('umap-help-link', container, translate('Help'))
|
||||
button.textContent = translate('Help')
|
||||
button.addEventListener('click', () => this.showGetStarted())
|
||||
return button
|
||||
}
|
||||
|
||||
parse(container) {
|
||||
for (const element of container.querySelectorAll('[data-help]')) {
|
||||
this.button(element, element.dataset.help.split(','))
|
||||
|
|
|
@ -27,6 +27,10 @@ export class MapPermissions extends ServerStored {
|
|||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
this._umap.render(['properties.permissions'])
|
||||
}
|
||||
|
||||
isOwner() {
|
||||
return Boolean(this._umap.properties.user?.is_owner)
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import { translate } from '../i18n.js'
|
|||
import { uMapAlert as Alert } from '../../components/alerts/alert.js'
|
||||
import * as Utils from '../utils.js'
|
||||
import * as Icon from './icon.js'
|
||||
import ContextMenu from '../ui/contextmenu.js'
|
||||
|
||||
// Those options are not saved on the server, so they can live here
|
||||
// instead of in umap.properties
|
||||
|
@ -104,10 +103,6 @@ const ControlsMixin = {
|
|||
},
|
||||
|
||||
renderControls: function () {
|
||||
const hasSlideshow = Boolean(this.options.slideshow?.active)
|
||||
const barEnabled = this.options.captionBar || hasSlideshow
|
||||
document.body.classList.toggle('umap-caption-bar-enabled', barEnabled)
|
||||
document.body.classList.toggle('umap-slideshow-enabled', hasSlideshow)
|
||||
for (const control of Object.values(this._controls)) {
|
||||
this.removeControl(control)
|
||||
}
|
||||
|
@ -150,198 +145,6 @@ const ControlsMixin = {
|
|||
if (this._umap.getProperty('scaleControl')) this._controls.scale.addTo(this)
|
||||
this._controls.tilelayers.setLayers()
|
||||
},
|
||||
|
||||
renderEditToolbar: function () {
|
||||
const className = 'umap-main-edit-toolbox'
|
||||
const container =
|
||||
document.querySelector(`.${className}`) ||
|
||||
DomUtil.create('div', `${className} with-transition dark`, this._controlContainer)
|
||||
container.innerHTML = ''
|
||||
const leftContainer = DomUtil.create('div', 'umap-left-edit-toolbox', container)
|
||||
const rightContainer = DomUtil.create('div', 'umap-right-edit-toolbox', container)
|
||||
const logo = DomUtil.create('div', 'logo', leftContainer)
|
||||
DomUtil.createLink('', logo, 'uMap', '/', null, translate('Go to the homepage'))
|
||||
const nameButton = DomUtil.createButton('map-name', leftContainer, '')
|
||||
DomEvent.on(nameButton, 'mouseover', () => {
|
||||
this._umap.tooltip.open({
|
||||
content: translate('Edit the title of the map'),
|
||||
anchor: nameButton,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
const shareStatusButton = DomUtil.createButton(
|
||||
'share-status',
|
||||
leftContainer,
|
||||
'',
|
||||
this._umap.permissions.edit,
|
||||
this._umap.permissions
|
||||
)
|
||||
DomEvent.on(shareStatusButton, 'mouseover', () => {
|
||||
this._umap.tooltip.open({
|
||||
content: translate('Update who can see and edit the map'),
|
||||
anchor: shareStatusButton,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
if (this.options.editMode === 'advanced') {
|
||||
DomEvent.on(nameButton, 'click', this._umap.editCaption, this._umap)
|
||||
DomEvent.on(
|
||||
shareStatusButton,
|
||||
'click',
|
||||
this._umap.permissions.edit,
|
||||
this._umap.permissions
|
||||
)
|
||||
}
|
||||
if (this.options.user?.id) {
|
||||
const button = U.Utils.loadTemplate(`
|
||||
<button class="umap-user flat" type="button">
|
||||
<i class="icon icon-16 icon-profile"></i>
|
||||
<span>${this.options.user.name}</span>
|
||||
</button>
|
||||
`)
|
||||
rightContainer.appendChild(button)
|
||||
const menu = new ContextMenu({ className: 'dark', fixed: true })
|
||||
const actions = [
|
||||
{
|
||||
label: translate('New map'),
|
||||
action: this._umap.urls.get('map_new'),
|
||||
},
|
||||
{
|
||||
label: translate('My maps'),
|
||||
action: this._umap.urls.get('user_dashboard'),
|
||||
},
|
||||
{
|
||||
label: translate('My teams'),
|
||||
action: this._umap.urls.get('user_teams'),
|
||||
},
|
||||
]
|
||||
if (this._umap.urls.has('user_profile')) {
|
||||
actions.push({
|
||||
label: translate('My profile'),
|
||||
action: this._umap.urls.get('user_profile'),
|
||||
})
|
||||
}
|
||||
button.addEventListener('click', () => {
|
||||
menu.openBelow(button, actions)
|
||||
})
|
||||
}
|
||||
|
||||
const connectedPeers = this._umap.sync.getNumberOfConnectedPeers()
|
||||
if (connectedPeers !== 0) {
|
||||
const connectedPeersCount = DomUtil.createButton(
|
||||
'leaflet-control-connected-peers',
|
||||
rightContainer,
|
||||
''
|
||||
)
|
||||
DomEvent.on(connectedPeersCount, 'mouseover', () => {
|
||||
this._umap.tooltip.open({
|
||||
content: translate(
|
||||
'{connectedPeers} peer(s) currently connected to this map',
|
||||
{
|
||||
connectedPeers: connectedPeers,
|
||||
}
|
||||
),
|
||||
anchor: connectedPeersCount,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
|
||||
const updateConnectedPeersCount = () => {
|
||||
connectedPeersCount.innerHTML = this._umap.sync.getNumberOfConnectedPeers()
|
||||
}
|
||||
updateConnectedPeersCount()
|
||||
}
|
||||
|
||||
this._umap.help.getStartedLink(rightContainer)
|
||||
const controlEditCancel = DomUtil.createButton(
|
||||
'leaflet-control-edit-cancel',
|
||||
rightContainer,
|
||||
DomUtil.add('span', '', null, translate('Cancel edits')),
|
||||
() => this._umap.askForReset()
|
||||
)
|
||||
DomEvent.on(controlEditCancel, 'mouseover', () => {
|
||||
this._umap.tooltip.open({
|
||||
content: this._umap.help.displayLabel('CANCEL'),
|
||||
anchor: controlEditCancel,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
const controlEditDisable = DomUtil.createButton(
|
||||
'leaflet-control-edit-disable',
|
||||
rightContainer,
|
||||
DomUtil.add('span', '', null, translate('View')),
|
||||
this._umap.disableEdit,
|
||||
this._umap
|
||||
)
|
||||
DomEvent.on(controlEditDisable, 'mouseover', () => {
|
||||
this._umap.tooltip.open({
|
||||
content: this._umap.help.displayLabel('PREVIEW'),
|
||||
anchor: controlEditDisable,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
const controlEditSave = DomUtil.createButton(
|
||||
'leaflet-control-edit-save button',
|
||||
rightContainer,
|
||||
DomUtil.add('span', '', null, translate('Save')),
|
||||
() => this._umap.saveAll()
|
||||
)
|
||||
DomEvent.on(controlEditSave, 'mouseover', () => {
|
||||
this._umap.tooltip.open({
|
||||
content: this._umap.help.displayLabel('SAVE'),
|
||||
anchor: controlEditSave,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
renderCaptionBar: function () {
|
||||
if (this.options.noControl) return
|
||||
const container =
|
||||
this._controlContainer.querySelector('.umap-caption-bar') ||
|
||||
DomUtil.create('div', 'umap-caption-bar', this._controlContainer)
|
||||
container.innerHTML = ''
|
||||
const name = DomUtil.create('h3', 'map-name', container)
|
||||
DomEvent.disableClickPropagation(container)
|
||||
this._umap.addAuthorLink(container)
|
||||
if (this._umap.getProperty('captionMenus')) {
|
||||
DomUtil.createButton(
|
||||
'umap-about-link flat',
|
||||
container,
|
||||
translate('Open caption'),
|
||||
() => this._umap.openCaption()
|
||||
)
|
||||
DomUtil.createButton(
|
||||
'umap-open-browser-link flat',
|
||||
container,
|
||||
translate('Browse data'),
|
||||
() => this.openBrowser('data')
|
||||
)
|
||||
if (this.options.facetKey) {
|
||||
DomUtil.createButton(
|
||||
'umap-open-filter-link flat',
|
||||
container,
|
||||
translate('Filter data'),
|
||||
() => this.openBrowser('filters')
|
||||
)
|
||||
}
|
||||
}
|
||||
this._umap.onceDatalayersLoaded(() => {
|
||||
this._umap.slideshow.renderToolbox(container)
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
const ManageTilelayerMixin = {
|
||||
|
@ -482,8 +285,6 @@ export const LeafletMap = BaseMap.extend({
|
|||
renderUI: function () {
|
||||
setOptions(this, this._umap.properties)
|
||||
this.initTileLayers()
|
||||
this.renderCaptionBar()
|
||||
this.renderEditToolbar()
|
||||
// Needs tilelayer to exist for minimap
|
||||
this.renderControls()
|
||||
this.handleLimitBounds()
|
||||
|
@ -576,6 +377,5 @@ export const LeafletMap = BaseMap.extend({
|
|||
|
||||
initEditTools: function () {
|
||||
this.editTools = new U.Editable(this._umap)
|
||||
this.renderEditToolbar()
|
||||
},
|
||||
})
|
||||
|
|
|
@ -26,13 +26,9 @@ export default class Slideshow extends WithTemplate {
|
|||
this.play()
|
||||
}, this)
|
||||
}
|
||||
leafletMap.on(
|
||||
'edit:enabled',
|
||||
function () {
|
||||
this.stop()
|
||||
},
|
||||
this
|
||||
)
|
||||
leafletMap.on('edit:enabled', () => {
|
||||
this.stop()
|
||||
})
|
||||
}
|
||||
|
||||
set current(feature) {
|
||||
|
@ -85,9 +81,13 @@ export default class Slideshow extends WithTemplate {
|
|||
spinner.style.animation = 'none'
|
||||
}
|
||||
|
||||
isEnabled() {
|
||||
return Boolean(this.properties.active)
|
||||
}
|
||||
|
||||
play() {
|
||||
if (this._id) return
|
||||
if (this._umap.editEnabled || !this._umap.properties.slideshow.active) return
|
||||
if (this._umap.editEnabled || !this.isEnabled()) return
|
||||
L.DomUtil.addClass(document.body, this.CLASSNAME)
|
||||
this._id = window.setInterval(L.bind(this.loop, this), this.properties.delay)
|
||||
this.startSpinner()
|
||||
|
|
187
umap/static/umap/js/modules/ui/bar.js
Normal file
187
umap/static/umap/js/modules/ui/bar.js
Normal file
|
@ -0,0 +1,187 @@
|
|||
import { DomEvent } from '../../../vendors/leaflet/leaflet-src.esm.js'
|
||||
import { translate } from '../i18n.js'
|
||||
import { WithTemplate } from '../utils.js'
|
||||
import ContextMenu from './contextmenu.js'
|
||||
|
||||
const TOP_BAR_TEMPLATE = `
|
||||
<div class="umap-main-edit-toolbox with-transition dark">
|
||||
<div class="umap-left-edit-toolbox" data-ref="left">
|
||||
<div class="logo"><a class="" href="/" title="${translate('Go to the homepage')}">uMap</a></div>
|
||||
<button class="map-name" type="button" data-ref="name"></button>
|
||||
<button class="share-status" type="button" data-ref="share"></button>
|
||||
</div>
|
||||
<div class="umap-right-edit-toolbox" data-ref="right">
|
||||
<button class="connected-peers" type="button" data-ref="peers"></button>
|
||||
<button class="umap-user flat" type="button" data-ref="user">
|
||||
<i class="icon icon-16 icon-profile"></i>
|
||||
<span class="username" data-ref="username"></span>
|
||||
</button>
|
||||
<button class="umap-help-link" type="button" title="${translate('Help')}" data-ref="help">${translate('Help')}</button>
|
||||
<button class="edit-cancel" type="button" data-ref="cancel">
|
||||
<span class="">${translate('Cancel edits')}</span>
|
||||
</button>
|
||||
<button class="edit-disable" type="button" data-ref="view">
|
||||
<span class="">${translate('View')}</span>
|
||||
</button>
|
||||
<button class="edit-save button" type="button" data-ref="save">
|
||||
<span class="">${translate('Save')}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
export class TopBar extends WithTemplate {
|
||||
constructor(umap, parent) {
|
||||
super()
|
||||
this._umap = umap
|
||||
this._menu = new ContextMenu({ className: 'dark', fixed: true })
|
||||
this.loadTemplate(TOP_BAR_TEMPLATE)
|
||||
this.parent = parent
|
||||
}
|
||||
|
||||
setup() {
|
||||
this.parent.appendChild(this.element)
|
||||
this.elements.name.addEventListener('mouseover', () => {
|
||||
this._umap.tooltip.open({
|
||||
content: translate('Edit the title of the map'),
|
||||
anchor: this.elements.name,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
this.elements.share.addEventListener('mouseover', () => {
|
||||
this._umap.tooltip.open({
|
||||
content: translate('Update who can see and edit the map'),
|
||||
anchor: this.elements.share,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
if (this._umap.properties.editMode === 'advanced') {
|
||||
this.elements.name.addEventListener('click', () => this._umap.editCaption())
|
||||
this.elements.share.addEventListener('click', () => this._umap.permissions.edit())
|
||||
}
|
||||
this.elements.user.addEventListener('click', () => {
|
||||
if (this._umap.properties.user?.id) {
|
||||
const actions = [
|
||||
{
|
||||
label: translate('New map'),
|
||||
action: this._umap.urls.get('map_new'),
|
||||
},
|
||||
{
|
||||
label: translate('My maps'),
|
||||
action: this._umap.urls.get('user_dashboard'),
|
||||
},
|
||||
{
|
||||
label: translate('My teams'),
|
||||
action: this._umap.urls.get('user_teams'),
|
||||
},
|
||||
]
|
||||
if (this._umap.urls.has('user_profile')) {
|
||||
actions.push({
|
||||
label: translate('My profile'),
|
||||
action: this._umap.urls.get('user_profile'),
|
||||
})
|
||||
}
|
||||
this._menu.openBelow(this.elements.user, actions)
|
||||
}
|
||||
})
|
||||
|
||||
const connectedPeers = this._umap.sync.getNumberOfConnectedPeers()
|
||||
this.elements.peers.dataset.connected = connectedPeers
|
||||
this.elements.peers.addEventListener('mouseover', () => {
|
||||
if (!connectedPeers) return
|
||||
this._umap.tooltip.open({
|
||||
content: translate('{connectedPeers} peer(s) currently connected to this map', {
|
||||
connectedPeers: connectedPeers,
|
||||
}),
|
||||
anchor: this.elements.peers,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
|
||||
this.elements.help.addEventListener('click', () => this._umap.showGetStarted())
|
||||
this.elements.cancel.addEventListener('click', () => this._umap.askForReset())
|
||||
this.elements.cancel.addEventListener('mouseover', () => {
|
||||
this._umap.tooltip.open({
|
||||
content: this._umap.help.displayLabel('CANCEL'),
|
||||
anchor: this.elements.cancel,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
this.elements.view.addEventListener('click', () => this._umap.disableEdit())
|
||||
this.elements.view.addEventListener('mouseover', () => {
|
||||
this._umap.tooltip.open({
|
||||
content: this._umap.help.displayLabel('PREVIEW'),
|
||||
anchor: this.elements.view,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
this.elements.save.addEventListener('click', () => this._umap.saveAll())
|
||||
this.elements.save.addEventListener('mouseover', () => {
|
||||
this._umap.tooltip.open({
|
||||
content: this._umap.help.displayLabel('SAVE'),
|
||||
anchor: this.elements.save,
|
||||
position: 'bottom',
|
||||
delay: 500,
|
||||
duration: 5000,
|
||||
})
|
||||
})
|
||||
this.redraw()
|
||||
}
|
||||
|
||||
redraw() {
|
||||
this.elements.peers.hidden = !this._umap.getProperty('syncEnabled')
|
||||
}
|
||||
}
|
||||
|
||||
const BOTTOM_BAR_TEMPLATE = `
|
||||
<div class="umap-caption-bar">
|
||||
<h3 class="map-name"></h3>
|
||||
<span data-ref="author"></span>
|
||||
<button class="umap-about-link flat" type="button" title="${translate('Open caption')}" data-ref="caption">${translate('Open caption')}</button>
|
||||
<button class="umap-open-browser-link flat" type="button" title="${translate('Browse data')}" data-ref="browse">${translate('Browse data')}</button>
|
||||
<button class="umap-open-browser-link flat" type="button" title="${translate('Filter data')}" data-ref="filter">${translate('Filter data')}</button>
|
||||
</div>
|
||||
`
|
||||
|
||||
export class BottomBar extends WithTemplate {
|
||||
constructor(umap, slideshow, parent) {
|
||||
super()
|
||||
this._umap = umap
|
||||
this._slideshow = slideshow
|
||||
this.loadTemplate(BOTTOM_BAR_TEMPLATE)
|
||||
this.parent = parent
|
||||
}
|
||||
|
||||
setup() {
|
||||
this.parent.appendChild(this.element)
|
||||
DomEvent.disableClickPropagation(this.element)
|
||||
this._umap.addAuthorLink(this.elements.author)
|
||||
this.elements.caption.addEventListener('click', () => this._umap.openCaption())
|
||||
this.elements.browse.addEventListener('click', () => this._umap.openBrowser('data'))
|
||||
this.elements.filter.addEventListener('click', () =>
|
||||
this._umap.openBrowser('filters')
|
||||
)
|
||||
this._slideshow.renderToolbox(this.element)
|
||||
this.redraw()
|
||||
}
|
||||
|
||||
redraw() {
|
||||
const hasSlideshow = this._slideshow.isEnabled()
|
||||
const barEnabled = this._umap.properties.captionBar || hasSlideshow
|
||||
document.body.classList.toggle('umap-caption-bar-enabled', barEnabled)
|
||||
document.body.classList.toggle('umap-slideshow-enabled', hasSlideshow)
|
||||
const showMenus = this._umap.getProperty('captionMenus')
|
||||
this.elements.caption.hidden = !showMenus
|
||||
this.elements.browse.hidden = !showMenus
|
||||
this.elements.filter.hidden = !showMenus || !this._umap.properties.facetKey
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ import { LeafletMap } from './rendering/map.js'
|
|||
import URLs from './urls.js'
|
||||
import { Panel, EditPanel, FullPanel } from './ui/panel.js'
|
||||
import Dialog from './ui/dialog.js'
|
||||
import { BottomBar, TopBar } from './ui/bar.js'
|
||||
import Tooltip from './ui/tooltip.js'
|
||||
import ContextMenu from './ui/contextmenu.js'
|
||||
import { Request, ServerRequest } from './request.js'
|
||||
|
@ -102,12 +103,14 @@ export default class Umap extends ServerStored {
|
|||
|
||||
this.panel = new Panel(this, this._leafletMap)
|
||||
this.dialog = new Dialog({ className: 'dark' })
|
||||
this.topBar = new TopBar(this, this._leafletMap._controlContainer)
|
||||
this.bottomBar = new BottomBar(
|
||||
this,
|
||||
this.slideshow,
|
||||
this._leafletMap._controlContainer
|
||||
)
|
||||
this.tooltip = new Tooltip(this._leafletMap._controlContainer)
|
||||
this.contextmenu = new ContextMenu()
|
||||
if (this.hasEditMode()) {
|
||||
this.editPanel = new EditPanel(this, this._leafletMap)
|
||||
this.fullPanel = new FullPanel(this, this._leafletMap)
|
||||
}
|
||||
this.server = new ServerRequest()
|
||||
this.request = new Request()
|
||||
this.facets = new Facets(this)
|
||||
|
@ -117,6 +120,13 @@ export default class Umap extends ServerStored {
|
|||
this.share = new Share(this)
|
||||
this.rules = new Rules(this)
|
||||
|
||||
if (this.hasEditMode()) {
|
||||
this.editPanel = new EditPanel(this, this._leafletMap)
|
||||
this.fullPanel = new FullPanel(this, this._leafletMap)
|
||||
this._leafletMap.initEditTools()
|
||||
this.topBar.setup()
|
||||
}
|
||||
|
||||
this.datalayersFromQueryString = this.searchParams.get('datalayers')
|
||||
if (this.datalayersFromQueryString) {
|
||||
this.datalayersFromQueryString = this.datalayersFromQueryString
|
||||
|
@ -180,14 +190,11 @@ export default class Umap extends ServerStored {
|
|||
await this.loadDataFromQueryString()
|
||||
}
|
||||
|
||||
if (this.hasEditMode()) {
|
||||
this._leafletMap.initEditTools()
|
||||
}
|
||||
|
||||
if (!this.properties.noControl) {
|
||||
this.initShortcuts()
|
||||
this._leafletMap.on('contextmenu', (e) => this.onContextMenu(e))
|
||||
this.onceDataLoaded(this.setViewFromQueryString)
|
||||
this.bottomBar.setup()
|
||||
this.propagate()
|
||||
}
|
||||
|
||||
|
@ -633,22 +640,6 @@ export default class Umap extends ServerStored {
|
|||
this.fire('saved')
|
||||
}
|
||||
|
||||
propagate() {
|
||||
let els = document.querySelectorAll('.map-name')
|
||||
for (const el of els) {
|
||||
el.textContent = this.getDisplayName()
|
||||
}
|
||||
const status = this.permissions.getShareStatusDisplay()
|
||||
els = document.querySelectorAll('.share-status')
|
||||
for (const el of els) {
|
||||
if (status) {
|
||||
el.textContent = translate('Visibility: {status}', {
|
||||
status: status,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getDisplayName() {
|
||||
return this.properties.name || translate('Untitled map')
|
||||
}
|
||||
|
@ -1004,7 +995,13 @@ export default class Umap extends ServerStored {
|
|||
],
|
||||
]
|
||||
const slideshowBuilder = new U.FormBuilder(this, slideshowFields, {
|
||||
callback: () => this.slideshow.load(),
|
||||
callback: () => {
|
||||
this.slideshow.load()
|
||||
// FIXME when we refactor formbuilder: this callback is called in a 'postsync'
|
||||
// event, which comes after the call of `setter` method, which will call the
|
||||
// map.render method, which should do this redraw.
|
||||
this.bottomBar.redraw()
|
||||
},
|
||||
umap: this,
|
||||
})
|
||||
slideshow.appendChild(slideshowBuilder.build())
|
||||
|
@ -1261,10 +1258,8 @@ export default class Umap extends ServerStored {
|
|||
}
|
||||
|
||||
render(fields) {
|
||||
if (fields.includes('numberOfConnectedPeers')) {
|
||||
this._leafletMap.renderEditToolbar()
|
||||
this.propagate()
|
||||
}
|
||||
const impacted = this.propagate(fields)
|
||||
if (impacted) return // No need to run a wider reflow
|
||||
|
||||
const impacts = Utils.getImpactsFromSchema(fields)
|
||||
for (const impact of impacts) {
|
||||
|
@ -1272,7 +1267,8 @@ export default class Umap extends ServerStored {
|
|||
case 'ui':
|
||||
this._leafletMap.renderUI()
|
||||
this.browser.redraw()
|
||||
this.propagate()
|
||||
this.topBar.redraw()
|
||||
this.bottomBar.redraw()
|
||||
break
|
||||
case 'data':
|
||||
this.eachVisibleDataLayer((datalayer) => {
|
||||
|
@ -1294,6 +1290,49 @@ export default class Umap extends ServerStored {
|
|||
}
|
||||
}
|
||||
|
||||
// This method does a targeted update of the UI,
|
||||
// it whould be merged with `render`` method and the
|
||||
// SCHEMA at some point
|
||||
propagate(fields = []) {
|
||||
const impacts = {
|
||||
'properties.name': () => {
|
||||
Utils.eachElement('.map-name', (el) => {
|
||||
el.textContent = this.getDisplayName()
|
||||
})
|
||||
},
|
||||
user: () => {
|
||||
Utils.eachElement('.umap-user .username', (el) => {
|
||||
if (this.properties.user?.id) {
|
||||
el.textContent = this.properties.user.name
|
||||
}
|
||||
})
|
||||
},
|
||||
'properties.permissions': () => {
|
||||
const status = this.permissions.getShareStatusDisplay()
|
||||
if (status) {
|
||||
Utils.eachElement('.share-status', (el) => {
|
||||
el.textContent = translate('Visibility: {status}', {
|
||||
status: status,
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
numberOfConnectedPeers: () => {
|
||||
Utils.eachElement('.connected-peers', (el) => {
|
||||
el.textContent = this.sync.getNumberOfConnectedPeers()
|
||||
})
|
||||
},
|
||||
}
|
||||
let impacted = false
|
||||
for (const [field, impact] of Object.entries(impacts)) {
|
||||
if (!fields.length || fields.includes(field)) {
|
||||
impact()
|
||||
impacted = true
|
||||
}
|
||||
}
|
||||
return impacted
|
||||
}
|
||||
|
||||
// TODO: allow to control the default datalayer
|
||||
// (edit and viewing)
|
||||
// cf https://github.com/umap-project/umap/issues/585
|
||||
|
|
|
@ -25,8 +25,6 @@ export function checkId(string) {
|
|||
return /^[A-Za-z0-9]{5}$/.test(string)
|
||||
}
|
||||
|
||||
|
||||
|
||||
function _getPropertyName(field) {
|
||||
const filtered_field = ['options.', 'properties.'].reduce(
|
||||
(acc, prefix) => acc.replace(prefix, ''),
|
||||
|
@ -440,3 +438,9 @@ export function deepEqual(object1, object2) {
|
|||
export function slugify(str) {
|
||||
return (str || 'data').replace(/[^a-z0-9]/gi, '_').toLowerCase()
|
||||
}
|
||||
|
||||
export function eachElement(selector, callback) {
|
||||
for (const el of document.querySelectorAll(selector)) {
|
||||
callback(el)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -389,7 +389,7 @@ U.EditControl = L.Control.extend({
|
|||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
const container = L.DomUtil.create('div', 'leaflet-control-edit-enable')
|
||||
const container = L.DomUtil.create('div', 'edit-enable')
|
||||
const enableEditing = L.DomUtil.createButton(
|
||||
'',
|
||||
container,
|
||||
|
|
|
@ -45,9 +45,6 @@ html[dir="rtl"] .leaflet-tooltip-pane > * {
|
|||
.umap-edit-enabled {
|
||||
--current-header-height: var(--header-height);
|
||||
}
|
||||
.umap-caption-bar-enabled {
|
||||
--current-footer-height: var(--footer-height);
|
||||
}
|
||||
.leaflet-top {
|
||||
top: var(--current-header-height);
|
||||
}
|
||||
|
@ -166,7 +163,7 @@ html[dir="rtl"] .leaflet-tooltip-pane > * {
|
|||
min-height: 23px;
|
||||
height: 23px;
|
||||
}
|
||||
.leaflet-control-edit-enable [type="button"]:before {
|
||||
.edit-enable [type="button"]:before {
|
||||
content: ' ';
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
|
@ -175,7 +172,7 @@ html[dir="rtl"] .leaflet-tooltip-pane > * {
|
|||
background-image: url('./img/16-white.svg');
|
||||
background-position: -48px -48px;
|
||||
}
|
||||
.leaflet-control-edit-enable [type="button"] {
|
||||
.edit-enable [type="button"] {
|
||||
width: initial;
|
||||
padding: 0 20px;
|
||||
background-color: #353c3e;
|
||||
|
@ -187,7 +184,7 @@ html[dir="rtl"] .leaflet-tooltip-pane > * {
|
|||
display: block;
|
||||
}
|
||||
.leaflet-control-toolbar .leaflet-toolbar-icon.dark:hover,
|
||||
.leaflet-control-edit-enable [type="button"]:hover {
|
||||
.edit-enable [type="button"]:hover {
|
||||
background-color: #4d5759;
|
||||
}
|
||||
.umap-permanent-credits-container {
|
||||
|
@ -476,245 +473,12 @@ ul.photon-autocomplete {
|
|||
.umap-edit-actions li:hover {
|
||||
background-color: #353c3e;
|
||||
}
|
||||
|
||||
|
||||
/* ********************************* */
|
||||
/* Edit main toolbox */
|
||||
/* ********************************* */
|
||||
.umap-main-edit-toolbox [type="button"] {
|
||||
color: #fff;
|
||||
font-size: 1.2em;
|
||||
border: none;
|
||||
background-color: var(--color-darkGray);
|
||||
width: auto;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.umap-main-edit-toolbox [type="button"]:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.leaflet-container [type="button"].umap-help-link {
|
||||
font-size: 12px;
|
||||
padding-bottom: 3px;
|
||||
background-color: inherit;
|
||||
}
|
||||
.leaflet-container .leaflet-control-edit-save,
|
||||
.leaflet-container .leaflet-control-edit-cancel,
|
||||
.leaflet-container .leaflet-control-edit-disable,
|
||||
.leaflet-container .leaflet-control-connected-peers
|
||||
{
|
||||
display: block;
|
||||
border: none;
|
||||
font-size: 12px;
|
||||
border-radius: 20px;
|
||||
color: #f8f8f8;
|
||||
height: 32px;
|
||||
line-height: 30px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.leaflet-container .leaflet-control-connected-peers,
|
||||
.dark [type="button"].leaflet-control-connected-peers:hover
|
||||
{
|
||||
background-color: var(--color-lightCyan);
|
||||
color: var(--color-dark);
|
||||
}
|
||||
|
||||
.leaflet-container .leaflet-control-edit-disable:before,
|
||||
.leaflet-container .leaflet-control-edit-save:before,
|
||||
.leaflet-container .leaflet-control-edit-cancel:before,
|
||||
.leaflet-container .leaflet-control-connected-peers:before {
|
||||
display: inline-block;
|
||||
width: 19px;
|
||||
height: 24px;
|
||||
background-position: -50px -122px;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url('./img/16-white.svg');
|
||||
vertical-align: middle;
|
||||
content: ' ';
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.leaflet-container .leaflet-control-connected-peers:before {
|
||||
background-image: url('./img/16.svg');
|
||||
}
|
||||
|
||||
.leaflet-container .leaflet-control-edit-disable span,
|
||||
.leaflet-container .leaflet-control-edit-save span,
|
||||
.leaflet-container .leaflet-control-edit-cancel span,
|
||||
.leaflet-container .leaflet-control-connected-peers span{
|
||||
margin-inline-start: 10px;
|
||||
}
|
||||
.leaflet-container .leaflet-control-edit-save:before {
|
||||
background-position: -148px -2px;
|
||||
}
|
||||
.leaflet-container .leaflet-control-edit-disable:before {
|
||||
background-position: -50px -25px;
|
||||
}
|
||||
.leaflet-container .leaflet-control-connected-peers:before {
|
||||
background-position: -2px -95px;
|
||||
}
|
||||
.leaflet-container .leaflet-control-edit-cancel,
|
||||
.leaflet-container .leaflet-control-edit-disable,
|
||||
.leaflet-container .leaflet-control-connected-peers{
|
||||
border: 0.5px solid rgba(153, 153, 153, 0.40);
|
||||
}
|
||||
.leaflet-container .leaflet-control-edit-cancel:hover,
|
||||
.leaflet-container .leaflet-control-edit-disable:hover {
|
||||
border: 0.5px solid rgba(153, 153, 153, 0.80);
|
||||
text-decoration: none;
|
||||
}
|
||||
.leaflet-container .leaflet-control-edit-save {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
border-radius: 16px;
|
||||
border: 0.5px solid rgba(153, 153, 153, 0.40);
|
||||
background: rgba(153, 153, 153, 0.10);
|
||||
}
|
||||
.dark [type="button"].leaflet-control-edit-save:hover {
|
||||
background: rgba(153, 153, 153, 0.10);
|
||||
text-decoration: none;
|
||||
}
|
||||
.umap-is-dirty .leaflet-control-edit-save {
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
border: 0.5px solid rgba(66, 236, 230, 0.40);
|
||||
background: rgba(66, 236, 230, 0.10);
|
||||
color: #42ECE6;
|
||||
}
|
||||
.umap-is-dirty .leaflet-control-edit-save:before {
|
||||
background-position: -148px -26px;
|
||||
}
|
||||
.umap-is-dirty .dark [type="button"].leaflet-control-edit-save:hover {
|
||||
border-color: rgba(66, 236, 230, 0.80);
|
||||
background: rgba(66, 236, 230, 0.10);
|
||||
}
|
||||
.leaflet-container .leaflet-control-edit-save,
|
||||
.leaflet-container .leaflet-control-edit-cancel,
|
||||
.leaflet-container .leaflet-control-edit-disable,
|
||||
.umap-edit-enabled .leaflet-control-edit-enable {
|
||||
display: none;
|
||||
}
|
||||
.umap-edit-enabled .leaflet-control-edit-save,
|
||||
.umap-edit-enabled .leaflet-control-edit-disable,
|
||||
.umap-edit-enabled.umap-is-dirty .leaflet-control-edit-cancel {
|
||||
display: inline-block;
|
||||
}
|
||||
.umap-is-dirty .leaflet-control-edit-disable {
|
||||
display: none;
|
||||
}
|
||||
.umap-caption-bar {
|
||||
display: none;
|
||||
}
|
||||
.umap-main-edit-toolbox {
|
||||
top: -46px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 46px;
|
||||
padding: 0 10px;
|
||||
text-align: start;
|
||||
line-height: var(--control-size);
|
||||
cursor: auto;
|
||||
border-bottom: 1px solid #222;
|
||||
z-index: var(--zindex-panels);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
}
|
||||
.umap-left-edit-toolbox,
|
||||
.umap-right-edit-toolbox {
|
||||
display: flex;
|
||||
column-gap: 10px;
|
||||
}
|
||||
.umap-right-edit-toolbox {
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.umap-main-edit-toolbox .logo {
|
||||
width: 39px;
|
||||
height: 100%;
|
||||
}
|
||||
.umap-main-edit-toolbox .logo a {
|
||||
background-image: url('./img/logo_small.svg');
|
||||
background-position: 0 center;
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
width: 39px;
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
text-indent: -9999px;
|
||||
}
|
||||
.umap-main-edit-toolbox .map-name {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
font-weight: bold;
|
||||
text-align: start;
|
||||
}
|
||||
.umap-main-edit-toolbox .share-status {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.map-name:after {
|
||||
content: '\00a0';
|
||||
padding-inline-start: 3px;
|
||||
width: 1ch;
|
||||
display: inline-block;
|
||||
}
|
||||
.umap-is-dirty .map-name:after {
|
||||
content: '*';
|
||||
}
|
||||
.umap-edit-enabled .umap-main-edit-toolbox {
|
||||
top: 0;
|
||||
}
|
||||
.umap-caption-bar h3,
|
||||
.umap-main-edit-toolbox h3 {
|
||||
display: inline;
|
||||
}
|
||||
.umap-caption-bar button {
|
||||
margin-inline-start: 10px;
|
||||
}
|
||||
.umap-caption-bar button + button:before {
|
||||
content: '|';
|
||||
padding-inline-end: 10px;
|
||||
}
|
||||
.umap-main-edit-toolbox .umap-user {
|
||||
color: #fff;
|
||||
}
|
||||
.umap-main-edit-toolbox .umap-user:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.umap-main-edit-toolbox .umap-user:after {
|
||||
content: '|';
|
||||
padding-inline-start: 20px;
|
||||
display: inline-block; /* Prevents underline on hover. */
|
||||
}
|
||||
.umap-caption-bar-enabled .umap-caption-bar {
|
||||
display: block;
|
||||
height: var(--footer-height);
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding: var(--gutter);
|
||||
text-align: start;
|
||||
line-height: 100%;
|
||||
cursor: auto;
|
||||
border-top: 1px solid var(--color-lightGray);
|
||||
opacity: 0.93;
|
||||
z-index: var(--zindex-panels);
|
||||
}
|
||||
.umap-help {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.umap-datalayer-version {
|
||||
padding: 5px 0;
|
||||
border-bottom: 1px solid #202425;
|
||||
|
|
|
@ -35,4 +35,5 @@
|
|||
<link rel="stylesheet" href="{% static 'umap/css/dialog.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'umap/css/importers.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'umap/css/tableeditor.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'umap/css/bar.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'umap/theme.css' %}" />
|
||||
|
|
Loading…
Reference in a new issue