chore: move editToolBar and captionBar to modules (#2272)

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:
Yohan Boniface 2024-11-19 13:30:10 +01:00 committed by GitHub
commit b678346d34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 533 additions and 1255 deletions

View file

@ -254,8 +254,8 @@ input[type="submit"] {
}
.dark .button,
.dark [type="button"] {
background-color: #2a2e30;
color: #eeeeec;
background-color: var(--color-darkerGray);
color: var(--text-color);
border: 1px solid #1b1f20;
}
.dark .button:hover,
@ -264,7 +264,7 @@ input[type="submit"] {
background-color: #2e3436;
}
.dark a {
color: #eeeeec;
color: var(--text-color);
}
button.flat,
[type="button"].flat,

View file

@ -0,0 +1,202 @@
.umap-main-edit-toolbox [type=button] {
color: #fff;
font-size: 1em;
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 {
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;
border-radius: 20px;
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-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);
}
.leaflet-container .icon-save {
display: none;
}
.dark 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: var(--color-brightCyan);
}
.umap-is-dirty .icon-save {
display: inline-block;
}
.umap-is-dirty .icon-save-disabled {
display: none;
}
.umap-is-dirty .dark 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 {
/* Show a transition from top to bottom when opening it */
top: calc(var(--header-height) * -1);
position: absolute;
width: 100%;
left: 0;
right: 0;
height: var(--header-height);
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-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: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 {
display: none;
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 .umap-caption-bar {
display: block;
}
.umap-caption-bar-enabled {
--current-footer-height: var(--footer-height);
}

View file

@ -8,7 +8,6 @@
background-color: initial;
}
.icon-16 {
background-image: url('../img/16.svg');
height: 24px;
line-height: 24px;
width: 24px;
@ -43,6 +42,14 @@ html[dir="rtl"] .icon {
.dark .icon-24 {
background-image: url('../img/24-white.svg');
}
.icon-16.icon-black,
.icon-16 {
background-image: url('../img/16.svg');
}
.icon-24.icon-black,
.icon-24 {
background-image: url('../img/24.svg');
}
.icon-add {
background-position: var(--tile) var(--tile);
}
@ -106,6 +113,9 @@ html[dir="rtl"] .icon {
.icon-marker {
background-position: calc(var(--tile) * 3) calc(var(--tile) * 5);
}
.icon-peers {
background-position: calc(var(--tile) * 3) calc(var(--tile) * 2);
}
.icon-polygon {
background-position: var(--tile) calc(var(--tile) * 3);
}
@ -124,6 +134,13 @@ html[dir="rtl"] .icon {
.expanded .icon-resize {
background-position: calc(var(--tile) * 2) calc(var(--tile) * 6);
}
.icon-save {
background-position: calc(var(--tile) * 6) var(--tile);
}
/* FIXME move to a 16-disabled.svg sprite ? */
.icon-save-disabled {
background-position: calc(var(--tile) * 6) 0;
}
.icon-search {
background-position: var(--tile) calc(var(--tile) * 5);
}

View file

@ -37,9 +37,6 @@
<path id="table-5" d="m54 819.36v2h12v-2zm0 3v1h4v-1zm5 0v1h7v-1zm-5 2v1h4v-1zm5 0v1h7v-1zm-5 2v1h4v-1zm5 0v1h7v-1zm-5 2v1h4v-1zm5 0v1h7v-1z" fill="#f2f2f2"/>
<path id="path3684" d="m63.714 866.36-1.1428 1.1429 2.2857 2.2857 1.1428-1.1429zm-1.7143 1.7143-6.2857 6.2857 2.2857 2.2857 6.2857-6.2857zm-6.2857 6.2857-1.7143 4 4-1.7143z" fill="#f2f2f2" stroke="#999" stroke-width=".25"/>
<text id="text4457-6" x="41.647079" y="916.79706" fill="#000000" font-family="sans-serif" letter-spacing="0px" word-spacing="0px" style="line-height:0%" xml:space="preserve"><tspan id="tspan4459-6" x="41.647079" y="916.79706" font-family="sans-serif" font-size="30.476px" style="line-height:1.25"> </tspan></text>
<g id="text4356-2" transform="translate(44 -124)" fill="#fff">
<path id="path4384-2" d="m35.742 999.44 3.0762-3.0762-3.0664-3.0664 1.1914-1.1914 3.0664 3.0664 3.0566-3.0566 1.1719 1.1816-3.0469 3.0566 3.0664 3.0664-1.1914 1.1914-3.0664-3.0664-3.0762 3.0762-1.1816-1.1816" fill="#f2f2f2"/>
</g>
<path id="path3684-2" d="m63.714 890.36-1.1428 1.1428 2.2857 2.2858 1.1428-1.1429zm-1.7143 1.7143-6.2857 6.2857 2.2857 2.2857 6.2857-6.2857zm-6.2857 6.2857-1.7143 4 4-1.7143z" fill="#b3b3b3"/>
<g id="g4717" transform="translate(-54.789 -114.48)">
<path id="path3862" transform="translate(-1.2108 854.84)" d="m141.27 173.42-6.7559 2.6797 0.95313 6.3457 5.8711 3.127 4.1484-7.873zm-1.4473 2.4883 2.9902 1.6016-0.5918 2.4316-3.3574 1.5039-1.7383-3.8106z" fill="#f2f2f2" fill-rule="evenodd" stroke="#999" stroke-width=".25"/>
@ -196,5 +193,14 @@
<path id="path11" d="m12 914.86a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5 2.5 2.5 0 0 0-2.5-2.5zm0 1a1.5 1.5 0 0 1 1.5 1.5 1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5z" style="paint-order:fill markers stroke"/>
</g>
</g>
<g id="g2-6" transform="matrix(1.22 0 0 1.22 75.51 864.01)" fill="none" stroke="#999" stroke-linecap="round" stroke-linejoin="round" stroke-width=".7">
<path id="path1-7" d="m2.5 4c0.82843 0 1.5-0.67157 1.5-1.5s-0.67157-1.5-1.5-1.5-1.5 0.67157-1.5 1.5 0.67157 1.5 1.5 1.5z"/>
<path id="path2-75" d="m4 5.3501h-3v2.39"/>
<path id="path3-3" d="m11.5 4c0.8284 0 1.5-0.67157 1.5-1.5s-0.6716-1.5-1.5-1.5-1.5 0.67157-1.5 1.5 0.6716 1.5 1.5 1.5z"/>
<path id="path4-5" d="m10 5.3501h3v2.39"/>
<path id="path5-6" d="m7 7.75c0.82843 0 1.5-0.67157 1.5-1.5s-0.67157-1.5-1.5-1.5-1.5 0.67157-1.5 1.5 0.67157 1.5 1.5 1.5z"/>
<path id="path6-6" d="m8.5 9.3501h-3v2.39"/>
<path id="path7-2" d="m5.5 9.3501h3v2.39"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg width="168" height="168" id="svg2" version="1.1" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)" sodipodi:docname="16-white.svg" inkscape:export-filename="16-white.png" inkscape:export-xdpi="96" inkscape:export-ydpi="96" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<svg width="168" height="168" id="svg2" version="1.1" inkscape:version="1.4 (e7c3feb100, 2024-10-09)" sodipodi:docname="16-white.svg" inkscape:export-filename="16-white.png" inkscape:export-xdpi="96" inkscape:export-ydpi="96" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs id="defs4">
<clipPath id="clip0_241_10857">
<rect width="18.049999" height="19.01" fill="#ffffff" id="rect586" x="0" y="0" />
@ -16,7 +16,7 @@
<path d="M 16.0401,2.3158 H 2.005 v 14.0351 h 14.0351 z" fill="#ffffff" id="path1259" />
</mask>
</defs>
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="3.8200527" inkscape:cx="86.517131" inkscape:cy="92.276214" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" inkscape:window-width="1920" inkscape:window-height="1011" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" showguides="true" inkscape:guide-bbox="true" inkscape:snap-grids="true" inkscape:snap-to-guides="true" inkscape:showpageshadow="2" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1">
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="11.587678" inkscape:cx="79.049488" inkscape:cy="68.779959" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" inkscape:window-width="1920" inkscape:window-height="1011" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" showguides="true" inkscape:guide-bbox="true" inkscape:snap-grids="true" inkscape:snap-to-guides="true" inkscape:showpageshadow="2" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1">
<inkscape:grid type="xygrid" id="grid3004" empspacing="4" visible="true" enabled="true" snapvisiblegridlinesonly="true" originx="0" originy="0" spacingy="1" spacingx="1" units="px" />
<sodipodi:guide orientation="-1,0" position="24,168" id="guide3084" inkscape:locked="false" inkscape:label="" inkscape:color="rgb(0,134,229)" />
<sodipodi:guide orientation="0,1" position="0,96" id="guide3086" inkscape:locked="false" inkscape:label="" inkscape:color="rgb(0,134,229)" />
@ -56,9 +56,6 @@
<g transform="translate(32,-48.000118)" style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#4d4d4d;fill-opacity:1;stroke:none" id="text3784-6" />
<path style="fill:#f2f2f2;fill-opacity:1;stroke:#999999;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m 63.71429,866.36213 -1.14285,1.14286 2.28571,2.28572 L 66,868.64785 Z M 62,868.07641 l -6.285714,6.28574 2.285715,2.2857 6.285719,-6.28572 z M 55.714286,874.36215 54,878.36214 l 4.000001,-1.71429 z" id="path3684" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccccccccc" />
<text xml:space="preserve" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" x="41.647079" y="916.79706" id="text4457-6"><tspan y="916.79706" x="41.647079" sodipodi:role="line" id="tspan4459-6" style="font-size:30.4762px;line-height:1.25;font-family:sans-serif"> </tspan></text>
<g id="text4356-2" style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none" transform="translate(44,-124.00004)">
<path inkscape:connector-curvature="0" id="path4384-2" style="font-variant:normal;font-stretch:normal;font-size:20px;font-family:Arial;-inkscape-font-specification:Arial;fill:#f2f2f2;fill-opacity:1" d="m 35.742187,999.43835 3.076172,-3.07617 -3.066406,-3.0664 1.191406,-1.19141 3.066407,3.06641 3.05664,-3.05664 1.171875,1.18164 -3.046875,3.05664 3.066406,3.0664 -1.191406,1.19138 L 40,997.54382 36.923828,1000.62 35.742187,999.43835" />
</g>
<path style="fill:#b3b3b3;fill-opacity:1;stroke:none" d="m 63.71429,890.36216 -1.14285,1.1428 2.28571,2.2858 L 66,892.64786 Z M 62,892.07646 55.714286,898.36218 58,900.64788 l 6.28572,-6.2857 z m -6.285714,6.28572 -1.714286,4 4,-1.7143 z" id="path3684-2" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccccccccc" />
<g id="g4717" transform="translate(-54.789185,-114.477)">
<path style="fill:#f2f2f2;fill-opacity:1;fill-rule:evenodd;stroke:#999999;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m 141.26953,173.42383 -6.75586,2.67969 0.95313,6.3457 5.87109,3.12695 4.14844,-7.87305 z m -1.44726,2.48828 2.99023,1.60156 -0.5918,2.43164 -3.35742,1.50391 -1.73828,-3.81055 z" transform="translate(-1.210815,854.83918)" id="path3862" inkscape:connector-curvature="0" />
@ -218,5 +215,14 @@
<path id="path11" style="fill:#f2f2f2;stroke:#999999;stroke-width:0.2;stroke-dasharray:none;paint-order:fill markers stroke" d="m 12,914.86218 a 2.5,2.5 0 0 0 -2.5,2.5 2.5,2.5 0 0 0 2.5,2.5 2.5,2.5 0 0 0 2.5,-2.5 2.5,2.5 0 0 0 -2.5,-2.5 z m 0,1 a 1.5,1.5 0 0 1 1.5,1.5 1.5,1.5 0 0 1 -1.5,1.5 1.5,1.5 0 0 1 -1.5,-1.5 1.5,1.5 0 0 1 1.5,-1.5 z" />
</g>
</g>
<g style="fill:none;stroke:#999999;stroke-opacity:1" id="g2-6" transform="matrix(1.2199965,0,0,1.2199965,75.510009,864.01174)">
<path d="m 2.5,4 c 0.82843,0 1.5,-0.67157 1.5,-1.5 0,-0.82843 -0.67157,-1.5 -1.5,-1.5 -0.82843,0 -1.5,0.67157 -1.5,1.5 0,0.82843 0.67157,1.5 1.5,1.5 z" stroke="#323737" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round" id="path1-7" style="stroke:#999999;stroke-opacity:1" />
<path d="m 4,5.3501 h -3 v 2.39" stroke="#323737" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round" id="path2-75" style="stroke:#999999;stroke-opacity:1" />
<path d="m 11.5,4 c 0.8284,0 1.5,-0.67157 1.5,-1.5 0,-0.82843 -0.6716,-1.5 -1.5,-1.5 -0.8284,0 -1.5,0.67157 -1.5,1.5 0,0.82843 0.6716,1.5 1.5,1.5 z" stroke="#323737" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round" id="path3-3" style="stroke:#999999;stroke-opacity:1" />
<path d="m 10,5.3501 h 3 v 2.39" stroke="#323737" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round" id="path4-5" style="stroke:#999999;stroke-opacity:1" />
<path d="m 7,7.75 c 0.82843,0 1.5,-0.67157 1.5,-1.5 0,-0.82843 -0.67157,-1.5 -1.5,-1.5 -0.82843,0 -1.5,0.67157 -1.5,1.5 0,0.82843 0.67157,1.5 1.5,1.5 z" stroke="#323737" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round" id="path5-6" style="stroke:#999999;stroke-opacity:1" />
<path d="m 8.5,9.3501 h -3 v 2.39" stroke="#323737" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round" id="path6-6" style="stroke:#999999;stroke-opacity:1" />
<path d="m 5.5,9.3501 h 3 v 2.39" stroke="#323737" stroke-width="0.7" stroke-linecap="round" stroke-linejoin="round" id="path7-2" style="stroke:#999999;stroke-opacity:1" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 74 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View file

@ -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(','))

View file

@ -27,6 +27,10 @@ export class MapPermissions extends ServerStored {
)
}
render() {
this._umap.render(['properties.permissions'])
}
isOwner() {
return Boolean(this._umap.properties.user?.is_owner)
}

View file

@ -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()
},
})

View file

@ -26,13 +26,9 @@ export default class Slideshow extends WithTemplate {
this.play()
}, this)
}
leafletMap.on(
'edit:enabled',
function () {
leafletMap.on('edit:enabled', () => {
this.stop()
},
this
)
})
}
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()

View file

@ -0,0 +1,193 @@
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 round" type="button" data-ref="peers">
<i class="icon icon-16 icon-peers icon-black"></i>
<span></span>
</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 round" type="button" data-ref="cancel">
<i class="icon icon-16 icon-restore"></i>
<span class="">${translate('Cancel edits')}</span>
</button>
<button class="edit-disable round" type="button" data-ref="view">
<i class="icon icon-16 icon-eye"></i>
<span class="">${translate('View')}</span>
</button>
<button class="edit-save button round" type="button" data-ref="save">
<i class="icon icon-16 icon-save"></i>
<i class="icon icon-16 icon-save-disabled"></i>
<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.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
}
}

View file

@ -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 span', (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

View file

@ -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)
}
}

View file

@ -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,

View file

@ -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;

View file

@ -5,6 +5,7 @@
--color-lightGray: #ddd;
--color-mediumGray: #3e4444;
--color-darkGray: #323737;
--color-darkerGray: #2a2e30;
--color-light: white;
--color-dark: black;
--color-limeGreen: #b9f5d2;

View file

@ -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' %}" />