Compare commits

...

12 commits

Author SHA1 Message Date
Yohan Boniface
f09ca48757
Merge f4ae51ae7e into f1f18ed518 2025-04-07 18:24:32 +02:00
Yohan Boniface
f1f18ed518
Remove confirm delete for features and datalayers (#2603)
Now that we have granular undo, I'd say we can simplify the delete
process.
2025-04-07 18:24:25 +02:00
Yohan Boniface
5e47a59d07
chore: refine main search form (#2608)
![image](https://github.com/user-attachments/assets/dd73a323-6f80-4b5b-8691-79a3f92f3723)
2025-04-07 18:23:52 +02:00
Yohan Boniface
a59b0110fc
chore: refine undo/redo buttons (#2605)
![image](https://github.com/user-attachments/assets/884b3a8c-ff4e-48e2-9bdf-16d31fb7512a)
2025-04-07 18:23:37 +02:00
Yohan Boniface
e1272ec6cd fix: do not cut kbd in tooltip
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-07 18:23:08 +02:00
Yohan Boniface
55babfde34
chore: refine map list card CSS (#2606) 2025-04-07 18:17:26 +02:00
Yohan Boniface
82b8564520 chore: refine undo/redo buttons
Co-authored-by: David Larlet <david@larlet.fr>
Co-authored-by: Aurélie Jallut <aurelie.jallut@beta.gouv.fr>
2025-04-07 18:16:37 +02:00
Yohan Boniface
5070a5e5b4 chore: refine main search form
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-07 18:11:49 +02:00
Yohan Boniface
06baeb718e fix: fix Textarea trying to clear this.input
Co-authored-by: David Larlet <david@larlet.fr>
2025-04-07 18:09:35 +02:00
Yohan Boniface
f186d3266c chore: refine map list card CSS
Co-authored-by: David Larlet <david@larlet.fr>
Co-authored-by: Aurélie Jallut <aurelie.jallut@beta.gouv.fr>
2025-04-07 16:34:09 +02:00
Yohan Boniface
49bba24b90 feat: remove confirm for feature delete 2025-04-07 10:48:34 +02:00
Yohan Boniface
a2749ce805 feat: remove confirm for datalayer delete
Now that we have granular undo, no needs for this I'd say.
2025-04-07 10:35:39 +02:00
22 changed files with 96 additions and 104 deletions

View file

@ -3,9 +3,7 @@
*/
body, div, ul, ol, li, a, section, nav,
h1, h2, h3, h4, h5, h6, label,
hr, input, textarea {
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
hr, input, textarea, select {
box-sizing: border-box;
margin: 0;
padding: 0;
@ -19,7 +17,11 @@ h1, h2, h3, h4, h5, h6, label, hr {
}
a {
text-decoration: none;
color: #1F5C39;
color: var(--link-color);
}
a.main {
font-weight: bold;
text-decoration: underline;
}
a[href^="http"]:not(nav.umap-nav a) {
text-decoration: underline;
@ -81,9 +83,6 @@ hgroup > * {
hgroup {
margin-bottom: var(--box-margin);
}
hgroup > :not(:first-child):last-child {
font-weight: normal;
}
hgroup p,
hgroup button {
margin: 0;
@ -202,6 +201,10 @@ dt {
/* Various */
/* *********** */
.nobr {
white-space: nowrap;
}
.text {
word-break: break-word;
white-space: pre-line;

View file

@ -19,7 +19,6 @@ input:-moz-placeholder, :-moz-placeholder {
.search-form {
display: flex;
align-items: baseline;
gap: calc(var(--gutter) / 2);
max-width: 800px;
margin: 0 auto;
}
@ -186,6 +185,8 @@ h2.tabs a:hover {
white-space: nowrap;
text-overflow: ellipsis;
vertical-align: middle;
font-size: small;
padding: 0 3px;
}
.card {
border: 1px solid var(--color-lightGray);
@ -213,7 +214,6 @@ h2.tabs a:hover {
/* colors */
/* **************************** */
input[type="submit"],
.button {
background-color: var(--button-primary-background);
color: var(--button-primary-color);
@ -405,22 +405,9 @@ html[dir="rtl"] .content .icon-delete {
align-items: center;
}
}
.table-header form input {
border: 2px solid var(--color-darkBlue);
border-radius: 0;
padding: .5rem 1rem;
margin-bottom: 0;
line-height: inherit;
height: 40px;
}
.table-header form input[type="search"] {
width: 30ch;
}
.table-header form input[type="submit"] {
background-color: var(--color-darkBlue);
color: white;
font-weight: bold;
}
.table-header .button-download {
width: inherit;

View file

@ -4,6 +4,7 @@
background-color: var(--color-darkGray);
width: auto;
margin-bottom: 0;
min-height: initial;
}
.umap-main-edit-toolbox [type=button]:hover {
text-decoration: underline;
@ -13,9 +14,14 @@
padding: 0 var(--text-margin);
background-color: inherit;
}
.leaflet-container .edit-undo {
margin-left: var(--box-margin);
}
.leaflet-container .edit-undo[disabled],
.leaflet-container .edit-redo[disabled] {
filter: invert(.5);
}
.leaflet-container .edit-save,
.leaflet-container .edit-undo,
.leaflet-container .edit-redo,
.leaflet-container .edit-disable,
.leaflet-container .connected-peers
{
@ -40,8 +46,6 @@
color: var(--color-darkGray);
}
.leaflet-container .edit-undo:hover,
.leaflet-container .edit-redo:hover,
.leaflet-container .edit-disable:hover {
border: 0.5px solid rgba(153, 153, 153, 0.80);
text-decoration: none;

View file

@ -7,16 +7,15 @@ input[type="datetime-local"], input[type="email"], input[type="number"],
input[type="search"], input[type="tel"], input[type="time"], input[type="file"],
input[type="url"], textarea {
background-color: white;
border: 1px solid #CCCCCC;
border-radius: 2px 2px 2px 2px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) inset;
color: rgba(0, 0, 0, 0.75);
border: 2px solid var(--color-darkBlue);
color: var(--text-color);
display: block;
font-family: inherit;
margin: 0;
margin-bottom: var(--box-margin);
padding: 7px;
padding: .5rem 1rem;
width: 100%;
line-height: inherit;
min-height: 40px;
}
input[type="range"] {
margin-top: 10px;
@ -47,11 +46,15 @@ input[type=checkbox]:checked:after {
content: '✓';
color: var(--color-darkGray);
}
input[data-modified=true] {
background-color: var(--color-lightCyan);
border: 1px solid var(--color-darkGray);
}
input + select,
select + input,
input + input {
border-left: none;
}
textarea {
height: inherit;
padding: 7px;
@ -59,13 +62,18 @@ textarea {
min-height: 6rlh;
}
select {
border: 1px solid #222;
border: 2px solid var(--color-darkBlue);
width: 100%;
padding: var(--button-padding);
background-color: var(--background-color);
color: var(--text-color);
min-height: 40px;
}
.dark select {
color: #efefef;
background-color: #393F3F;
color: var(--text-color);
background-color: var(--color-darkGray);
border-color: var(--color-dark);
border-width: 1px;
}
select[multiple="multiple"] {
height: auto;
@ -75,16 +83,16 @@ select[multiple="multiple"] {
input[type="submit"] {
display: flex;
align-items: center;
margin-bottom: 14px;
text-align: center;
border-radius: 2px;
font-weight: normal;
cursor: pointer;
padding: var(--button-padding);
border: none;
text-decoration: none;
background-color: white;
justify-content: center;
background-color: var(--color-darkBlue);
color: white;
font-weight: normal;
min-height: 40px;
}
.dark .button,
.dark [type="button"] {
@ -92,6 +100,9 @@ input[type="submit"] {
color: var(--text-color);
border: 1px solid #1b1f20;
}
.button.primary {
font-weight: bold;
}
.dark .button.primary:not([disabled]),
.dark [type="button"].primary:not([disabled]) {
background-color: var(--color-brightCyan);
@ -160,6 +171,14 @@ input + .help-text {
.formbox.with-switch {
padding-top: 2px;
}
.with-switch {
overflow: hidden;
}
.formbox select,
.formbox textarea,
.formbox input {
margin-bottom: var(--text-margin);
}
fieldset.formbox {
border: none;
border-top: 1px solid var(--color-lightGray);
@ -200,8 +219,9 @@ input[value]:invalid {
background-color: darkred;
}
.dark input, .dark textarea {
background-color: #232729;
border-color: #1b1f20;
background-color: var(--color-darkerGray);
border-color: var(--color-dark);
border-width: 1px;
color: #efefef;
}
details {
@ -277,9 +297,6 @@ input.switch:empty ~ label {
text-indent: 6em;
margin: 0.2em 0;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
text-shadow: 0 1px rgba(0, 0, 0, 0.1);
width: 80px;
@ -567,6 +584,7 @@ input.blur {
vertical-align: middle;
border-start-end-radius: 0;
border-end-end-radius: 0;
margin-bottom: 0;
}
.blur + .button,
.blur + [type="button"] {

View file

@ -61,7 +61,7 @@ export default class Browser {
DomEvent.on(zoom_to, 'click', viewFeature)
DomEvent.on(title, 'click', viewFeature)
DomEvent.on(edit, 'click', feature.edit, feature)
DomEvent.on(del, 'click', feature.confirmDelete, feature)
DomEvent.on(del, 'click', feature.del, feature)
// HOTFIX. Remove when this is released:
// https://github.com/Leaflet/Leaflet/pull/9052
DomEvent.disableClickPropagation(row)

View file

@ -278,7 +278,8 @@ class Feature {
<i class="icon icon-24 icon-delete"></i>${translate('Delete')}
</button>`)
button.addEventListener('click', () => {
this.confirmDelete().then(() => this._umap.editPanel.close())
this.del()
this._umap.editPanel.close()
})
container.appendChild(button)
}
@ -363,17 +364,6 @@ class Feature {
return popup.loadContent()
}
async confirmDelete() {
const confirmed = await this._umap.dialog.confirm(
translate('Are you sure you want to delete the feature?')
)
if (confirmed) {
this.del()
return true
}
return false
}
del(sync) {
this.isDirty = true
this._umap._leafletMap.closePopup()
@ -518,7 +508,7 @@ class Feature {
icon: 'icon-edit',
},
{
action: () => this.confirmDelete(),
action: () => this.del(),
title: translate('Delete this feature'),
icon: 'icon-delete',
},
@ -673,7 +663,7 @@ class Feature {
},
{
label: translate('Delete this feature'),
action: () => this.confirmDelete(),
action: () => this.del(),
},
{
label: translate('Clone this feature'),

View file

@ -1237,23 +1237,14 @@ export class DataLayer {
translate('Delete layer')
)
if (this.isReadOnly()) {
DomUtil.addClass(container, 'readonly')
container.classList.add('readonly')
} else {
DomEvent.on(edit, 'click', this.edit, this)
DomEvent.on(table, 'click', this.tableEdit, this)
DomEvent.on(
remove,
'click',
function () {
if (!this.isVisible()) return
this._umap.dialog
.confirm(translate('Are you sure you want to delete this layer?'))
.then(() => {
this.del()
})
},
this
)
edit.addEventListener('click', () => this.edit())
table.addEventListener('click', () => this.tableEdit())
remove.addEventListener('click', () => {
if (!this.isVisible()) return
this.del()
})
}
DomEvent.on(toggle, 'click', () => this.toggle())
DomEvent.on(zoomTo, 'click', this.zoomTo, this)

View file

@ -152,7 +152,9 @@ Fields.Textarea = class extends BaseElement {
this.textarea.value = value
}
}
clear() {
this.textarea.value = ''
}
value() {
return this.textarea.value
}

View file

@ -196,7 +196,7 @@ export default class Help {
.split('+')
.map((el) => `<kbd>${el}</kbd>`)
.join('+')
label += ` ${shortcut}`
label += ` <span class="nobr">${shortcut}</span>`
} else {
label += ` (${shortcut})`
}

View file

@ -11,13 +11,11 @@ const TOP_BAR_TEMPLATE = `
<div class="logo"><a class="" href="/" title="${translate('Go to the homepage')}">uMap</a></div>
<button class="map-name flat truncate" type="button" data-ref="name"></button>
<button class="share-status flat truncate" type="button" data-ref="share"></button>
<button class="edit-undo round" type="button" data-ref="undo" disabled>
<button class="edit-undo round flat" type="button" data-ref="undo" disabled>
<i class="icon icon-16 icon-undo"></i>
<span>${translate('Undo')}</span>
</button>
<button class="edit-redo round" type="button" data-ref="redo" disabled>
<button class="edit-redo round flat" type="button" data-ref="redo" disabled>
<i class="icon icon-16 icon-redo"></i>
<span>${translate('Redo')}</span>
</button>
</div>
<div class="umap-right-edit-toolbox" data-ref="right">

View file

@ -126,6 +126,7 @@ export function escapeHTML(s) {
'frameborder',
'scrolling',
'controls',
'class',
],
ALLOWED_ATTR: ['href', 'src', 'width', 'height', 'style', 'dir', 'title', 'type'],
// Added: `geo:` URL scheme as defined in RFC5870:

View file

@ -37,7 +37,6 @@ html[dir="rtl"] .leaflet-tooltip-pane > * {
background-color: var(--color-lightGray);
}
/* *********** */
/* Structure */
/* *********** */
@ -94,6 +93,8 @@ html[dir="rtl"] .leaflet-tooltip-pane > * {
background-image: url('./img/24.svg');
text-indent: -9999px;
margin-bottom: 0;
background-color: white;
min-height: initial;
}
.leaflet-control.display-on-more,
.umap-control-less {
@ -449,7 +450,7 @@ ul.photon-autocomplete {
display: inline-block;
width: 16px;
height: 16px;
margin-inline-start: 5px;
margin-inline-start: 2px;
background-position: 2px -4px;
background-repeat: no-repeat;
background-image: url('./img/16.svg');
@ -470,6 +471,7 @@ ul.photon-autocomplete {
}
.umap-getstarted button {
width: 100%;
margin-bottom: var(--text-margin);
}
.umap-help {
font-style: italic;
@ -660,6 +662,10 @@ a.umap-control-caption,
.umap-caption .header i.icon {
flex-shrink: 0;
}
.umap-caption button {
background-color: var(--background-color);
color: var(--text-color);
}
.umap-browser .main-toolbox {
padding-left: 4px; /* Align with toolbox below */
border-top: 1px solid var(--color-mediumGray);

View file

@ -1,6 +1,5 @@
:root {
/* Colors. */
--color-waterMint: #B9F5D2;
--color-darkBlue: #263B58;
--color-lighterGray: #f6f6f6;
--color-lightGray: #ddd;
@ -12,16 +11,17 @@
--color-limeGreen: #b9f5d2;
--color-brightCyan: #46ece6;
--color-lightCyan: #d4fbf9;
--color-darkCyan: #43a39f;
--color-darkCyan: #009099;
--color-red: #c60f13;
--color-darkRed: #5b2a2a;
--background-color: var(--color-light);
--color-accent: var(--color-brightCyan);
--text-color: var(--color-dark);
--link-color: var(--color-darkCyan);
/* Buttons. */
--button-primary-background: var(--color-waterMint);
--button-primary-background: var(--color-limeGreen);
--button-primary-color: var(--color-darkBlue);
--button-neutral-background: var(--color-lightGray);
--button-neutral-color: var(--color-darkGray);

View file

@ -12,14 +12,14 @@
{% endfor %}
</ul>
{% endif %}
<h3><a href="{{ map_inst.get_absolute_url }}">{{ map_inst.name }}</a></h3>
<h3>{{ map_inst.name }}</h3>
{% with author=map_inst.get_author %}
{% if author %}
<p>{% trans "by" %} <a href="{{ author.get_url }}">{{ author }}</a></p>
{% endif %}
{% endwith %}
</div>
<a class="button" href="{{ map_inst.get_absolute_url }}">{% translate "See the map" %}</a>
<a class="main" href="{{ map_inst.get_absolute_url }}">{% translate "See the map" %}</a>
</hgroup>
</div>
{% endfor %}

View file

@ -16,7 +16,7 @@
<option value="{{ value }}" {% if request.GET.tags == value %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
<input type="submit" value="{% trans "Search" %}" class="neutral" />
<input type="submit" value="{% trans "Search" %}" />
</form>
</div>
</div>

View file

@ -348,9 +348,8 @@ def test_should_redraw_list_on_feature_delete(live_server, openmap, page, bootst
buttons = page.locator(".umap-browser .datalayer li .icon-delete")
expect(buttons).to_have_count(3)
buttons.first.click()
page.locator("dialog").get_by_role("button", name="OK").click()
expect(buttons).to_have_count(2)
page.get_by_role("button", name="Undo").click()
page.locator(".edit-undo").click()
expect(buttons).to_have_count(3)

View file

@ -261,7 +261,7 @@ def test_can_create_new_rule(live_server, page, openmap):
page.get_by_title("AliceBlue").first.click()
colors = getColors(markers)
assert colors.count("rgb(240, 248, 255)") == 3
page.get_by_role("button", name="Undo").click()
page.locator(".edit-undo").click()
colors = getColors(markers)
assert colors.count("rgb(240, 248, 255)") == 0

View file

@ -61,10 +61,9 @@ def test_cancel_deleting_datalayer_should_restore(
expect(markers).to_have_count(1)
page.get_by_role("button", name="Manage layers").click()
page.locator(".panel.right").get_by_title("Delete layer").click()
page.get_by_role("button", name="OK").click()
expect(markers).to_have_count(0)
expect(page.get_by_text("test datalayer")).to_be_hidden()
page.get_by_role("button", name="Undo").click()
page.locator(".edit-undo").click()
expect(markers).to_have_count(1)
expect(page.locator(".umap-browser").get_by_text("test datalayer")).to_be_visible()
@ -203,7 +202,6 @@ def test_deleting_datalayer_should_remove_from_browser_and_layers_list(
expect(panel.get_by_text("test datalayer")).to_be_visible()
expect(edit_panel.get_by_text("test datalayer")).to_be_visible()
page.locator(".panel.right").get_by_title("Delete layer").click()
page.get_by_role("button", name="OK").click()
expect(panel.get_by_text("test datalayer")).to_be_hidden()
expect(edit_panel.get_by_text("test datalayer")).to_be_hidden()
@ -217,7 +215,6 @@ def test_deleting_datalayer_should_remove_from_caption(
page.get_by_role("button", name="Manage layers").click()
expect(panel.get_by_text("test datalayer")).to_be_visible()
page.locator(".panel.right").get_by_title("Delete layer").click()
page.get_by_role("button", name="OK").click()
expect(panel.get_by_text("test datalayer")).to_be_hidden()

View file

@ -117,7 +117,7 @@ def test_should_reset_style_on_cancel(live_server, openmap, page, bootstrap):
expect(page.locator(".leaflet-overlay-pane path[fill='GoldenRod']")).to_have_count(
1
)
page.get_by_role("button", name="Undo").click()
page.locator(".edit-undo").click()
expect(page.locator(".leaflet-overlay-pane path[fill='DarkBlue']")).to_have_count(1)

View file

@ -241,7 +241,6 @@ def test_can_delete_datalayer(live_server, map, login, datalayer):
expect(markers).to_have_count(1)
page.get_by_role("button", name="Manage layers").click()
page.locator(".panel.right").get_by_title("Delete layer").click()
page.get_by_role("button", name="OK").click()
with page.expect_response(re.compile(r".*/datalayer/delete/.*")):
page.get_by_role("button", name="Save").click()
expect(markers).to_have_count(0)

View file

@ -16,7 +16,7 @@ def test_reseting_map_would_remove_from_save_queue(
page.on("request", register_request)
page.locator('input[name="name"]').click()
page.locator('input[name="name"]').fill("new name")
page.get_by_role("button", name="Undo").click()
page.locator(".edit-undo").click()
page.wait_for_timeout(500)
page.get_by_role("button", name="Manage layers").click()
page.get_by_role("button", name="Edit", exact=True).click()

View file

@ -86,7 +86,6 @@ def test_websocket_connection_can_sync_markers(new_page, asgi_live_server, tilel
# Delete a marker from peer A and check it's been deleted on peer B
a_first_marker.click(button="right")
peerA.get_by_role("button", name="Delete this feature").click()
peerA.locator("dialog").get_by_role("button", name="OK").click()
expect(a_marker_pane).to_have_count(1)
expect(b_marker_pane).to_have_count(1)
@ -166,7 +165,6 @@ def test_websocket_connection_can_sync_polygons(context, asgi_live_server, tilel
# Delete a polygon from peer A and check it's been deleted on peer B
a_polygon.click(button="right")
peerA.get_by_role("button", name="Delete this feature").click()
peerA.locator("dialog").get_by_role("button", name="OK").click()
expect(a_polygons).to_have_count(0)
expect(b_polygons).to_have_count(0)
@ -485,7 +483,6 @@ def test_should_sync_datalayers_delete(new_page, asgi_live_server, tilelayer):
# Delete "datalayer 2" in peerA
peerA.locator(".datalayer").get_by_role("button", name="Delete layer").first.click()
peerA.get_by_role("button", name="OK").click()
expect(peerA.locator(".panel").get_by_text("datalayer 2")).to_be_hidden()
expect(peerB.locator(".panel").get_by_text("datalayer 2")).to_be_hidden()
@ -686,7 +683,7 @@ def test_should_sync_datalayer_clear(
expect(peerB.locator(".leaflet-marker-icon")).to_have_count(0)
# Undo in peer A
peerA.get_by_role("button", name="Undo").click()
peerA.locator(".edit-undo").click()
expect(peerA.locator(".leaflet-marker-icon")).to_have_count(1)
expect(peerB.locator(".leaflet-marker-icon")).to_have_count(1)