wip: add a way to remove data from a layer from a condition

This commit is contained in:
Yohan Boniface 2024-07-01 18:55:52 +02:00
parent 6976fd1f63
commit 628e74ecb3
3 changed files with 71 additions and 25 deletions

View file

@ -11,7 +11,7 @@ import Help from './help.js'
import Importer from './importer.js' import Importer from './importer.js'
import Orderable from './orderable.js' import Orderable from './orderable.js'
import { HTTPError, NOKError, Request, RequestError, ServerRequest } from './request.js' import { HTTPError, NOKError, Request, RequestError, ServerRequest } from './request.js'
import Rules from './rules.js' import { Rule, Rules } from './rules.js'
import { SCHEMA } from './schema.js' import { SCHEMA } from './schema.js'
import { SyncEngine } from './sync/engine.js' import { SyncEngine } from './sync/engine.js'
import Dialog from './ui/dialog.js' import Dialog from './ui/dialog.js'
@ -44,6 +44,7 @@ window.U = {
Panel, Panel,
Request, Request,
RequestError, RequestError,
Rule,
Rules, Rules,
SCHEMA, SCHEMA,
ServerRequest, ServerRequest,

View file

@ -2,7 +2,7 @@ import { DomEvent, DomUtil, stamp } from '../../vendors/leaflet/leaflet-src.esm.
import { translate } from './i18n.js' import { translate } from './i18n.js'
import * as Utils from './utils.js' import * as Utils from './utils.js'
class Rule { export class Rule {
get condition() { get condition() {
return this._condition return this._condition
} }
@ -12,20 +12,10 @@ class Rule {
this.parse() this.parse()
} }
get isDirty() { constructor(condition = '') {
return this._isDirty
}
set isDirty(status) {
this._isDirty = status
if (status) this.map.isDirty = status
}
constructor(map, condition = '', options = {}) {
// TODO make this public properties when browser coverage is ok // TODO make this public properties when browser coverage is ok
// cf https://caniuse.com/?search=public%20class%20field // cf https://caniuse.com/?search=public%20class%20field
this._condition = null this._condition = null
this._isDirty = false
this.OPERATORS = [ this.OPERATORS = [
['>', this.gt], ['>', this.gt],
['<', this.lt], ['<', this.lt],
@ -34,16 +24,9 @@ class Rule {
['!=', this.not_equal], ['!=', this.not_equal],
['=', this.equal], ['=', this.equal],
] ]
this.map = map
this.active = true
this.options = options
this.condition = condition this.condition = condition
} }
render(fields) {
this.map.render(fields)
}
equal(other) { equal(other) {
return this.expected === other return this.expected === other
} }
@ -85,9 +68,37 @@ class Rule {
} }
match(props) { match(props) {
if (!this.operator || !this.active) return false if (!this.operator) return false
return this.operator(this.cast(props[this.key])) return this.operator(this.cast(props[this.key]))
} }
}
class ConditionalRule extends Rule {
get isDirty() {
return this._isDirty
}
set isDirty(status) {
this._isDirty = status
if (status) this.map.isDirty = status
}
match(props) {
if (!this.active) return false
return super.match(props)
}
constructor(map, condition = '', options = {}) {
super()
this._isDirty = false
this.map = map
this.active = true
this.options = options
}
render(fields) {
this.map.render(fields)
}
getMap() { getMap() {
return this.map return this.map
@ -170,7 +181,7 @@ class Rule {
} }
} }
export default class Rules { export class Rules {
constructor(map) { constructor(map) {
this.map = map this.map = map
this.rules = [] this.rules = []
@ -181,7 +192,7 @@ export default class Rules {
if (!this.map.options.rules?.length) return if (!this.map.options.rules?.length) return
for (const { condition, options } of this.map.options.rules) { for (const { condition, options } of this.map.options.rules) {
if (!condition) continue if (!condition) continue
this.rules.push(new Rule(this.map, condition, options)) this.rules.push(new ConditionalRule(this.map, condition, options))
} }
} }
@ -218,7 +229,7 @@ export default class Rules {
} }
addRule() { addRule() {
const rule = new Rule(this.map) const rule = new ConditionalRule(this.map)
rule.isDirty = true rule.isDirty = true
this.rules.push(rule) this.rules.push(rule)
rule.edit(map) rule.edit(map)

View file

@ -101,6 +101,34 @@ U.TableEditor = L.Class.extend({
}) })
}, },
refine: function () {
const promise = new U.Prompt().open({
className: 'dark',
title: L._('Deleting rows matching condition'),
})
promise.then((raw) => {
if (!raw) return
const rule = new U.Rule(raw)
const matched = []
this.datalayer.eachLayer((feature) => {
if (rule.match(feature.properties)) {
matched.push(feature)
}
})
if (!matched) {
U.Alert.error(L._('Nothing matched'))
return
}
this.datalayer.hide()
for (const feature of matched) {
feature.del()
}
this.datalayer.isDirty = true
this.datalayer.show()
this.edit()
})
},
edit: function () { edit: function () {
const id = 'tableeditor:edit' const id = 'tableeditor:edit'
this.compileProperties() this.compileProperties()
@ -115,10 +143,16 @@ U.TableEditor = L.Class.extend({
const iconElement = L.DomUtil.createIcon(addButton, 'icon-add') const iconElement = L.DomUtil.createIcon(addButton, 'icon-add')
addButton.insertBefore(iconElement, addButton.firstChild) addButton.insertBefore(iconElement, addButton.firstChild)
L.DomEvent.on(addButton, 'click', this.addProperty, this) L.DomEvent.on(addButton, 'click', this.addProperty, this)
const refineButton = L.DomUtil.createButton('flat', undefined, L._('Delete rows'))
refineButton.insertBefore(
L.DomUtil.createIcon(refineButton, 'icon-add'),
refineButton.firstChild
)
L.DomEvent.on(refineButton, 'click', this.refine, this)
this.datalayer.map.fullPanel.open({ this.datalayer.map.fullPanel.open({
content: this.table, content: this.table,
className: 'umap-table-editor', className: 'umap-table-editor',
actions: [addButton], actions: [addButton, refineButton],
}) })
}, },
}) })