From 034023fe1f3fe5b896f4eef8ecb0b9bcdf6eef81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sat, 19 Aug 2017 08:46:41 +0200 Subject: [PATCH 01/33] CategoryOverpass: Specify filters on results (basic commit) --- lang/de.json | 1 + lang/en.json | 1 + src/CategoryOverpass.js | 51 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/lang/de.json b/lang/de.json index 4584dd53..2b1ffe34 100644 --- a/lang/de.json +++ b/lang/de.json @@ -16,6 +16,7 @@ "export:OSMJSON": "", "export:OSMXML": null, "facilities": "Einrichtungen", + "filter_results": "Ergebnisse einschränken", "header:attributes": "Attribute", "header:export": "Export", "header:osm_meta": "OSM Meta", diff --git a/lang/en.json b/lang/en.json index e12e7304..4f0cd3ea 100644 --- a/lang/en.json +++ b/lang/en.json @@ -16,6 +16,7 @@ "export:OSMJSON": "Download as OSM JSON", "export:OSMXML": "Download as OSM XML", "facilities": "Facilities", + "filter_results": "Filter results", "header:attributes": "Attributes", "header:export": "Export", "header:osm_meta": "OSM Meta", diff --git a/src/CategoryOverpass.js b/src/CategoryOverpass.js index 7725dcd7..43e4daa2 100644 --- a/src/CategoryOverpass.js +++ b/src/CategoryOverpass.js @@ -108,7 +108,48 @@ function CategoryOverpass (options, data) { this.layer.on('remove', (ob, data) => this.emit('remove', ob, data)) this.layer.on('zoomChange', (ob, data) => this.emit('remove', ob, data)) - p = document.createElement('div') + if (this.data.filter) { + this.domFilter = document.createElement('form') + + this.formFilter = new form(this.id, this.data.filter, + { + 'type': 'form_chooser', + 'button:add_element': '-- ' + lang('filter_results') + ' --', + 'order': false + } + ) + this.formFilter.show(this.domFilter) + this.formFilter.onchange = function () { + var data = this.formFilter.get_data() + + this.additionalFilter = [] + for (var k in data) { + if (data[k] === null) { + continue + } + + var d = this.data.filter[k] + + var v = { + key: k, + value: data[k], + op: '=' + } + + if ('op' in d) { + v.op = d.op + } + + this.additionalFilter.push(v) + } + + this.layer.options.queryOptions.filter = this.additionalFilter + this.layer.check_update_map() + }.bind(this) + this.dom.insertBefore(this.domFilter, this.domContent) + } + + var p = document.createElement('div') p.className = 'loadingIndicator' p.innerHTML = '' + lang('loading') + '' this.dom.appendChild(p) @@ -193,6 +234,14 @@ CategoryOverpass.prototype.load = function (callback) { }.bind(this)) } +CategoryOverpass.prototype.setParentDom = function (parentDom) { + CategoryBase.prototype.setParentDom.call(this, parentDom) + + if (this.formFilter) { + this.formFilter.resize() + } +} + CategoryOverpass.prototype.setMap = function (map) { CategoryBase.prototype.setMap.call(this, map) From 1e4e5048e20b7ccc25a847c3a6878de2cc631d7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sat, 11 Aug 2018 21:17:21 +0200 Subject: [PATCH 02/33] Repository*: don't convert array->string in 'filter' --- src/RepositoryDir.php | 2 +- src/RepositoryGit.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RepositoryDir.php b/src/RepositoryDir.php index bab69884..37385c7e 100644 --- a/src/RepositoryDir.php +++ b/src/RepositoryDir.php @@ -26,7 +26,7 @@ class RepositoryDir extends RepositoryBase { continue; } - $data['categories'][$m[1]] = jsonMultilineStringsJoin($d1, array('exclude' => array(array('const')))); + $data['categories'][$m[1]] = jsonMultilineStringsJoin($d1, array('exclude' => array(array('const'), array('filter')))); } if (preg_match("/^(detailsBody|popupBody).html$/", $f, $m)) { diff --git a/src/RepositoryGit.php b/src/RepositoryGit.php index d35ff30b..503f037c 100644 --- a/src/RepositoryGit.php +++ b/src/RepositoryGit.php @@ -48,7 +48,7 @@ class RepositoryGit extends RepositoryBase { continue; } - $data['categories'][$id] = jsonMultilineStringsJoin($d1, array('exclude' => array(array('const')))); + $data['categories'][$id] = jsonMultilineStringsJoin($d1, array('exclude' => array(array('const'), array('filter')))); } if (preg_match("/^[0-9]{6} blob [0-9a-f]{40}\t((detailsBody|popupBody)\.html)$/", $r, $m)) { From f9ee1939a66bd8b73b8305ba36f1d7fa0507543f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sat, 11 Aug 2018 22:02:04 +0200 Subject: [PATCH 03/33] CategoryOverpass: translations for filters --- src/CategoryOverpass.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/CategoryOverpass.js b/src/CategoryOverpass.js index 43e4daa2..3aad988a 100644 --- a/src/CategoryOverpass.js +++ b/src/CategoryOverpass.js @@ -111,6 +111,33 @@ function CategoryOverpass (options, data) { if (this.data.filter) { this.domFilter = document.createElement('form') + for (var k in this.data.filter) { + let f = this.data.filter[k] + if ('name' in f && typeof f.name === 'string') { + let t = OverpassLayer.twig.twig({ data: f.name, autoescape: true }) + f.name = t.render({}).toString() + } else if (!('name' in f)) { + f.name = lang('tag:' + k) + } + + if ('values' in f) { + if (Array.isArray(f.values)) { + let newValues = {} + f.values.forEach(v => { + newValues[v] = lang('tag:' + k + '=' + v) + }) + f.values = newValues + } else if (typeof f.values === 'object') { + for (var k1 in f.values) { + if (typeof f.values[k1] === 'string') { + let t = OverpassLayer.twig.twig({ data: f.values[k1], autoescape: true }) + f.values[k1] = t.render({}).toString() + } + } + } + } + } + this.formFilter = new form(this.id, this.data.filter, { 'type': 'form_chooser', From c17724927eb4d5c55886dc4265289526e2ca48f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sun, 12 Aug 2018 13:11:11 +0200 Subject: [PATCH 04/33] CategoryOverpass: special filter operator 'has_key_value' --- src/CategoryOverpass.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/CategoryOverpass.js b/src/CategoryOverpass.js index 3aad988a..e7ff4e78 100644 --- a/src/CategoryOverpass.js +++ b/src/CategoryOverpass.js @@ -164,7 +164,14 @@ function CategoryOverpass (options, data) { } if ('op' in d) { - v.op = d.op + if (d.op === 'has_key_value') { + v = { + key: data[k], + op: 'has_key' + } + } else { + v.op = d.op + } } this.additionalFilter.push(v) From 2f4257c277fe673981aef5de2eb512b30e3366e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sat, 20 Oct 2018 22:31:10 +0200 Subject: [PATCH 05/33] CategoryOverpass: Show filter within tab --- src/CategoryOverpass.js | 10 +++++++++- style.css | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/CategoryOverpass.js b/src/CategoryOverpass.js index e7ff4e78..b7bfdeda 100644 --- a/src/CategoryOverpass.js +++ b/src/CategoryOverpass.js @@ -109,7 +109,16 @@ function CategoryOverpass (options, data) { this.layer.on('zoomChange', (ob, data) => this.emit('remove', ob, data)) if (this.data.filter) { + this.tabFilter = new tabs.Tab({ + id: 'filter' + }) + this.tools.add(this.tabFilter) + + this.tabFilter.header.innerHTML = '' + this.tabFilter.header.title = lang('filter') + this.domFilter = document.createElement('form') + this.tabFilter.content.appendChild(this.domFilter) for (var k in this.data.filter) { let f = this.data.filter[k] @@ -180,7 +189,6 @@ function CategoryOverpass (options, data) { this.layer.options.queryOptions.filter = this.additionalFilter this.layer.check_update_map() }.bind(this) - this.dom.insertBefore(this.domFilter, this.domContent) } var p = document.createElement('div') diff --git a/style.css b/style.css index f832b3e4..3571b2f4 100644 --- a/style.css +++ b/style.css @@ -427,3 +427,7 @@ a:active { .overpass-layer-icon .sign { white-space: nowrap; } + +.tabs-section > form > span.form_element_form_chooser { + border: none; +} From 5bfa532a9433dc33f1b283c555567eaefc8c5774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sun, 21 Oct 2018 19:15:37 +0200 Subject: [PATCH 06/33] CategoryOverpass/Filter: add parameter to url resp. read; improve form handling --- src/CategoryOverpass.js | 114 +++++++++++++++++++++++++++------------- src/categories.js | 16 +++++- 2 files changed, 93 insertions(+), 37 deletions(-) diff --git a/src/CategoryOverpass.js b/src/CategoryOverpass.js index b7bfdeda..28e29ec6 100644 --- a/src/CategoryOverpass.js +++ b/src/CategoryOverpass.js @@ -3,6 +3,8 @@ var OpenStreetBrowserLoader = require('./OpenStreetBrowserLoader') var OverpassLayer = require('overpass-layer') var OverpassLayerList = require('overpass-layer').List +var queryString = require('query-string') + var CategoryBase = require('./CategoryBase') var state = require('./state') var tabs = require('modulekit-tabs') @@ -120,6 +122,8 @@ function CategoryOverpass (options, data) { this.domFilter = document.createElement('form') this.tabFilter.content.appendChild(this.domFilter) + this.tabFilter.on('select', () => this.formFilter.resize()) + for (var k in this.data.filter) { let f = this.data.filter[k] if ('name' in f && typeof f.name === 'string') { @@ -156,38 +160,12 @@ function CategoryOverpass (options, data) { ) this.formFilter.show(this.domFilter) this.formFilter.onchange = function () { - var data = this.formFilter.get_data() - - this.additionalFilter = [] - for (var k in data) { - if (data[k] === null) { - continue - } + let param = JSON.parse(JSON.stringify(this.formFilter.get_data())) - var d = this.data.filter[k] + this._applyParam(param) - var v = { - key: k, - value: data[k], - op: '=' - } - - if ('op' in d) { - if (d.op === 'has_key_value') { - v = { - key: data[k], - op: 'has_key' - } - } else { - v.op = d.op - } - } - - this.additionalFilter.push(v) - } - - this.layer.options.queryOptions.filter = this.additionalFilter this.layer.check_update_map() + state.update() }.bind(this) } @@ -218,7 +196,23 @@ function CategoryOverpass (options, data) { state.categories = '' } - state.categories += this.id + let id = this.id + + if (this.formFilter) { + let param = JSON.parse(JSON.stringify(this.formFilter.get_data())) + + for (var k in param) { + if (!param[k]) { + delete param[k] + } + } + + if (param && Object.keys(param).length) { + id += '[' + queryString.stringify(param) + ']' + } + } + + state.categories += id } }.bind(this)) @@ -227,8 +221,17 @@ function CategoryOverpass (options, data) { return } - var list = state.categories.split(',') - if (list.indexOf(this.id) === -1) { + let list = state.categories.split(',') + let found = list.filter(id => { + let m = id.match(/^([0-9A-Z_-]+)(\[(.*)\])/i) + if (m) { + id = m[1] + } + + return id === this.id + }).length + + if (!found) { this.close() } @@ -236,6 +239,45 @@ function CategoryOverpass (options, data) { }.bind(this)) } +CategoryOverpass.prototype.setParam = function (param) { + this.formFilter.set_data(param) + this._applyParam(param) +} + +CategoryOverpass.prototype._applyParam = function (param) { + this.additionalFilter = [] + for (var k in param) { + if (param[k] === null) { + continue + } + + var d = this.data.filter[k] + + var v = { + key: k, + value: param[k], + op: '=' + } + + if ('op' in d) { + if (d.op === 'has_key_value') { + v = { + key: param[k], + op: 'has_key' + } + } else { + v.op = d.op + } + } + + this.additionalFilter.push(v) + } + + this.layer.options.queryOptions.filter = this.additionalFilter + + this.tabFilter.select() +} + CategoryOverpass.prototype.updateAssets = function (div) { var imgs = div.getElementsByTagName('img') for (var i = 0; i < imgs.length; i++) { @@ -278,10 +320,6 @@ CategoryOverpass.prototype.load = function (callback) { CategoryOverpass.prototype.setParentDom = function (parentDom) { CategoryBase.prototype.setParentDom.call(this, parentDom) - - if (this.formFilter) { - this.formFilter.resize() - } } CategoryOverpass.prototype.setMap = function (map) { @@ -435,6 +473,10 @@ CategoryOverpass.prototype.open = function () { this.updateInfo() } + + if (this.formFilter) { + this.formFilter.resize() + } } CategoryOverpass.prototype.updateInfo = function () { diff --git a/src/categories.js b/src/categories.js index 4c6c5152..c7615b68 100644 --- a/src/categories.js +++ b/src/categories.js @@ -1,3 +1,5 @@ +var queryString = require('query-string') + var OpenStreetBrowserLoader = require('./OpenStreetBrowserLoader') register_hook('state-apply', function (state) { @@ -7,6 +9,14 @@ register_hook('state-apply', function (state) { var list = state.categories.split(',') list.forEach(function (id) { + let param + + let m = id.match(/^([0-9A-Z_-]+)(\[(.*)\])/i) + if (m) { + id = m[1] + param = queryString.parse(m[3]) + } + OpenStreetBrowserLoader.getCategory(id, function (err, category) { if (err) { console.log("Can't load category " + id + ': ', err) @@ -14,11 +24,15 @@ register_hook('state-apply', function (state) { } if (category) { - category.open() + if (param) { + category.setParam(param) + } if (!category.parentDom) { category.setParentDom(document.getElementById('contentListAddCategories')) } + category.open() + } }) }) From 74376bacf8b5a48619b0bfa608ddbed5dbf9ba18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Mon, 22 Oct 2018 21:49:34 +0200 Subject: [PATCH 07/33] CategoryOverpass: filter: option valueName -> template for rendering name of value --- src/CategoryOverpass.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/CategoryOverpass.js b/src/CategoryOverpass.js index 28e29ec6..f7660924 100644 --- a/src/CategoryOverpass.js +++ b/src/CategoryOverpass.js @@ -134,10 +134,11 @@ function CategoryOverpass (options, data) { } if ('values' in f) { - if (Array.isArray(f.values)) { + if (Array.isArray(f.values) && f.valueName) { + let template = OverpassLayer.twig.twig({ data: f.valueName, autoescape: true }) let newValues = {} - f.values.forEach(v => { - newValues[v] = lang('tag:' + k + '=' + v) + f.values.forEach(value => { + newValues[value] = template.render({ value }).toString() }) f.values = newValues } else if (typeof f.values === 'object') { From dcc0c3677b5e9d6819a3acfb23142030a517bd63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Wed, 24 Oct 2018 10:59:37 +0200 Subject: [PATCH 08/33] CategoryOverpass: move filter to separate file, extend function via events --- package.json | 3 +- src/CategoryOverpass.js | 114 ++++-------------------------- src/CategoryOverpassFilter.js | 128 ++++++++++++++++++++++++++++++++++ src/index.js | 1 + 4 files changed, 143 insertions(+), 103 deletions(-) create mode 100644 src/CategoryOverpassFilter.js diff --git a/package.json b/package.json index 0992b57a..a2e8b41e 100644 --- a/package.json +++ b/package.json @@ -11,13 +11,14 @@ "@mapbox/maki": "^5.0.0", "async": "^2.5.0", "async-foreach": "^0.1.3", - "babelify": "^8.0.0", "babel-cli": "^6.26.0", "babel-core": "^6.26.0", "babel-preset-env": "^1.6.1", + "babelify": "^8.0.0", "color-interpolate": "^1.0.2", "event-emitter": "^0.3.5", "file-saver": "^2.0.0", + "font-awesome": "^4.7.0", "i18next-client": "^1.11.4", "ip-location": "^1.0.1", "json-multiline-strings": "^0.1.0", diff --git a/src/CategoryOverpass.js b/src/CategoryOverpass.js index f7660924..03695e1a 100644 --- a/src/CategoryOverpass.js +++ b/src/CategoryOverpass.js @@ -110,65 +110,8 @@ function CategoryOverpass (options, data) { this.layer.on('remove', (ob, data) => this.emit('remove', ob, data)) this.layer.on('zoomChange', (ob, data) => this.emit('remove', ob, data)) - if (this.data.filter) { - this.tabFilter = new tabs.Tab({ - id: 'filter' - }) - this.tools.add(this.tabFilter) - - this.tabFilter.header.innerHTML = '' - this.tabFilter.header.title = lang('filter') - - this.domFilter = document.createElement('form') - this.tabFilter.content.appendChild(this.domFilter) - - this.tabFilter.on('select', () => this.formFilter.resize()) - - for (var k in this.data.filter) { - let f = this.data.filter[k] - if ('name' in f && typeof f.name === 'string') { - let t = OverpassLayer.twig.twig({ data: f.name, autoescape: true }) - f.name = t.render({}).toString() - } else if (!('name' in f)) { - f.name = lang('tag:' + k) - } - - if ('values' in f) { - if (Array.isArray(f.values) && f.valueName) { - let template = OverpassLayer.twig.twig({ data: f.valueName, autoescape: true }) - let newValues = {} - f.values.forEach(value => { - newValues[value] = template.render({ value }).toString() - }) - f.values = newValues - } else if (typeof f.values === 'object') { - for (var k1 in f.values) { - if (typeof f.values[k1] === 'string') { - let t = OverpassLayer.twig.twig({ data: f.values[k1], autoescape: true }) - f.values[k1] = t.render({}).toString() - } - } - } - } - } - this.formFilter = new form(this.id, this.data.filter, - { - 'type': 'form_chooser', - 'button:add_element': '-- ' + lang('filter_results') + ' --', - 'order': false - } - ) - this.formFilter.show(this.domFilter) - this.formFilter.onchange = function () { - let param = JSON.parse(JSON.stringify(this.formFilter.get_data())) - - this._applyParam(param) - - this.layer.check_update_map() - state.update() - }.bind(this) - } + call_hooks('category-overpass-init', this) var p = document.createElement('div') p.className = 'loadingIndicator' @@ -199,18 +142,17 @@ function CategoryOverpass (options, data) { let id = this.id - if (this.formFilter) { - let param = JSON.parse(JSON.stringify(this.formFilter.get_data())) + let param = {} + this.emit('stateGet', param) - for (var k in param) { - if (!param[k]) { - delete param[k] - } + for (var k in param) { + if (!param[k]) { + delete param[k] } + } - if (param && Object.keys(param).length) { - id += '[' + queryString.stringify(param) + ']' - } + if (param && Object.keys(param).length) { + id += '[' + queryString.stringify(param) + ']' } state.categories += id @@ -241,42 +183,12 @@ function CategoryOverpass (options, data) { } CategoryOverpass.prototype.setParam = function (param) { - this.formFilter.set_data(param) + this.emit('setParam', param) this._applyParam(param) } CategoryOverpass.prototype._applyParam = function (param) { - this.additionalFilter = [] - for (var k in param) { - if (param[k] === null) { - continue - } - - var d = this.data.filter[k] - - var v = { - key: k, - value: param[k], - op: '=' - } - - if ('op' in d) { - if (d.op === 'has_key_value') { - v = { - key: param[k], - op: 'has_key' - } - } else { - v.op = d.op - } - } - - this.additionalFilter.push(v) - } - - this.layer.options.queryOptions.filter = this.additionalFilter - - this.tabFilter.select() + this.emit('applyParam', param) } CategoryOverpass.prototype.updateAssets = function (div) { @@ -475,9 +387,7 @@ CategoryOverpass.prototype.open = function () { this.updateInfo() } - if (this.formFilter) { - this.formFilter.resize() - } + this.emit('open') } CategoryOverpass.prototype.updateInfo = function () { diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js new file mode 100644 index 00000000..1b46dc44 --- /dev/null +++ b/src/CategoryOverpassFilter.js @@ -0,0 +1,128 @@ +const OverpassLayer = require('overpass-layer') +const tabs = require('modulekit-tabs') + +const state = require('./state') + +class CategoryOverpassFilter { + constructor (master) { + this.master = master + this.data = this.master.data.filter + + this.tabFilter = new tabs.Tab({ + id: 'filter' + }) + this.master.tools.add(this.tabFilter) + + this.tabFilter.header.innerHTML = '' + this.tabFilter.header.title = lang('filter') + + this.domFilter = document.createElement('form') + this.tabFilter.content.appendChild(this.domFilter) + + this.tabFilter.on('select', () => this.formFilter.resize()) + + for (var k in this.data) { + let f = this.data[k] + if ('name' in f && typeof f.name === 'string') { + let t = OverpassLayer.twig.twig({ data: f.name, autoescape: true }) + f.name = t.render({}).toString() + } else if (!('name' in f)) { + f.name = lang('tag:' + k) + } + + if ('values' in f) { + if (Array.isArray(f.values) && f.valueName) { + let template = OverpassLayer.twig.twig({ data: f.valueName, autoescape: true }) + let newValues = {} + f.values.forEach(value => { + newValues[value] = template.render({ value }).toString() + }) + f.values = newValues + } else if (typeof f.values === 'object') { + for (var k1 in f.values) { + if (typeof f.values[k1] === 'string') { + let t = OverpassLayer.twig.twig({ data: f.values[k1], autoescape: true }) + f.values[k1] = t.render({}).toString() + } + } + } + } + } + + this.formFilter = new form('filter-' + this.master.id, this.data, + { + 'type': 'form_chooser', + 'button:add_element': '-- ' + lang('filter_results') + ' --', + 'order': false + } + ) + this.formFilter.show(this.domFilter) + this.formFilter.onchange = function () { + let param = JSON.parse(JSON.stringify(this.formFilter.get_data())) + + this.applyParam(param) + + this.master.layer.check_update_map() + state.update() + }.bind(this) + + this.master.on('setParam', param => this.formFilter.set_data(param)) + this.master.on('applyParam', param => this.applyParam(param)) + this.master.on('open', () => this.openCategory()) + this.master.on('stateGet', param => this.stateGet(param)) + } + + applyParam (param) { + this.additionalFilter = [] + for (var k in param) { + if (param[k] === null) { + continue + } + + var d = this.data[k] + + var v = { + key: k, + value: param[k], + op: '=' + } + + if ('op' in d) { + if (d.op === 'has_key_value') { + v = { + key: param[k], + op: 'has_key' + } + } else { + v.op = d.op + } + } + + this.additionalFilter.push(v) + } + + this.master.layer.options.queryOptions.filter = this.additionalFilter + + this.tabFilter.select() + } + + openCategory () { + this.formFilter.resize() + } + + stateGet (param) { + let data = this.formFilter.get_data() + + for (var k in data) { + if (data[k]) { + param[k] = data[k] + } + } + } +} + +register_hook('category-overpass-init', (category) => { + if (category.data.filter) { + new CategoryOverpassFilter(category) + } +}) diff --git a/src/index.js b/src/index.js index 65350567..26d9c093 100644 --- a/src/index.js +++ b/src/index.js @@ -35,6 +35,7 @@ require('./wikipedia') require('./image') require('./addCategories') require('./permalink') +require('./CategoryOverpassFilter') let exportAll = require('./exportAll') window.onload = function () { From e2998bcd91776f304c4a4d9a139744f6185e776c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Wed, 24 Oct 2018 11:02:38 +0200 Subject: [PATCH 09/33] Filter: optionally specify different key --- src/CategoryOverpassFilter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js index 1b46dc44..7aac6679 100644 --- a/src/CategoryOverpassFilter.js +++ b/src/CategoryOverpassFilter.js @@ -82,7 +82,7 @@ class CategoryOverpassFilter { var d = this.data[k] var v = { - key: k, + key: 'key' in d ? d.key : k, value: param[k], op: '=' } From c4e09e1eff6ed217b7f16f7eacec1e93faf49b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Wed, 24 Oct 2018 11:07:27 +0200 Subject: [PATCH 10/33] CategoryOverpassFilter: bind function to events --- src/CategoryOverpassFilter.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js index 7aac6679..eb395236 100644 --- a/src/CategoryOverpassFilter.js +++ b/src/CategoryOverpassFilter.js @@ -66,10 +66,14 @@ class CategoryOverpassFilter { state.update() }.bind(this) - this.master.on('setParam', param => this.formFilter.set_data(param)) - this.master.on('applyParam', param => this.applyParam(param)) - this.master.on('open', () => this.openCategory()) - this.master.on('stateGet', param => this.stateGet(param)) + this.master.on('setParam', this.setParam.bind(this)) + this.master.on('applyParam', this.applyParam.bind(this)) + this.master.on('open', this.openCategory.bind(this)) + this.master.on('stateGet', this.stateGet.bind(this)) + } + + setParam (param) { + this.formFilter.set_data(param) } applyParam (param) { From 39402b774e1256c59ba817e46b223fd1c6b03ea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Fri, 26 Oct 2018 22:08:13 +0200 Subject: [PATCH 11/33] CategoryOverpassFilter: filters may define custom queries --- src/CategoryOverpassFilter.js | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js index eb395236..72e122d1 100644 --- a/src/CategoryOverpassFilter.js +++ b/src/CategoryOverpassFilter.js @@ -2,6 +2,7 @@ const OverpassLayer = require('overpass-layer') const tabs = require('modulekit-tabs') const state = require('./state') +const Filter = require('overpass-frontend').Filter class CategoryOverpassFilter { constructor (master) { @@ -43,6 +44,11 @@ class CategoryOverpassFilter { if (typeof f.values[k1] === 'string') { let t = OverpassLayer.twig.twig({ data: f.values[k1], autoescape: true }) f.values[k1] = t.render({}).toString() + } else if (typeof f.values[k1] === 'object') { + if (f.values[k1].name) { + let t = OverpassLayer.twig.twig({ data: f.values[k1].name, autoescape: true }) + f.values[k1].name = t.render({}).toString() + } } } } @@ -78,6 +84,8 @@ class CategoryOverpassFilter { applyParam (param) { this.additionalFilter = [] + let kvFilter = [] + for (var k in param) { if (param[k] === null) { continue @@ -85,6 +93,12 @@ class CategoryOverpassFilter { var d = this.data[k] + if ('values' in d && param[k] in d.values && typeof d.values[param[k]] === 'object' && 'query' in d.values[param[k]]) { + let f = new Filter(d.values[param[k]].query) + this.additionalFilter.push(f.def) + continue + } + var v = { key: 'key' in d ? d.key : k, value: param[k], @@ -102,7 +116,19 @@ class CategoryOverpassFilter { } } - this.additionalFilter.push(v) + kvFilter.push(v) + } + + if (kvFilter.length) { + this.additionalFilter.push(kvFilter) + } + + if (this.additionalFilter.length === 0) { + this.additionalFilter = [] + } else if (this.additionalFilter.length === 1) { + this.additionalFilter = this.additionalFilter[0] + } else { + this.additionalFilter = { and: this.additionalFilter } } this.master.layer.options.queryOptions.filter = this.additionalFilter From 99dbc6fb95915d119d5f125c536d91f1cb033072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Tue, 8 Jan 2019 15:21:00 +0100 Subject: [PATCH 12/33] Translation: Rename 'filter_results' to 'choose_filter' --- lang/ast.json | 1 + lang/ca.json | 1 + lang/cs.json | 1 + lang/da.json | 1 + lang/de.json | 2 +- lang/el.json | 1 + lang/en.json | 2 +- lang/es.json | 1 + lang/et.json | 1 + lang/fr.json | 1 + lang/hu.json | 1 + lang/it.json | 1 + lang/ja.json | 1 + lang/nl.json | 1 + lang/pl.json | 1 + lang/pt-br.json | 1 + lang/pt.json | 1 + lang/ro.json | 1 + lang/ru.json | 1 + lang/sr.json | 1 + lang/template.json | 1 + lang/uk.json | 1 + src/CategoryOverpassFilter.js | 2 +- 23 files changed, 23 insertions(+), 3 deletions(-) diff --git a/lang/ast.json b/lang/ast.json index 92ab783e..61b8e5ca 100644 --- a/lang/ast.json +++ b/lang/ast.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/ca.json b/lang/ca.json index bd8ed25c..1338834f 100644 --- a/lang/ca.json +++ b/lang/ca.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/cs.json b/lang/cs.json index d498d933..03c56e06 100644 --- a/lang/cs.json +++ b/lang/cs.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/da.json b/lang/da.json index 00ddf730..26db7984 100644 --- a/lang/da.json +++ b/lang/da.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/de.json b/lang/de.json index 2b1ffe34..0938b89c 100644 --- a/lang/de.json +++ b/lang/de.json @@ -3,6 +3,7 @@ "back": "zurück", "categories": "", "category-info-tooltip": "Info & Legende", + "choose_filter": "Filter wählen", "closed": "geschlossen", "default": "Standard", "edit": "bearbeiten", @@ -16,7 +17,6 @@ "export:OSMJSON": "", "export:OSMXML": null, "facilities": "Einrichtungen", - "filter_results": "Ergebnisse einschränken", "header:attributes": "Attribute", "header:export": "Export", "header:osm_meta": "OSM Meta", diff --git a/lang/el.json b/lang/el.json index df6fb441..f18a9c35 100644 --- a/lang/el.json +++ b/lang/el.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/en.json b/lang/en.json index 4f0cd3ea..0f775070 100644 --- a/lang/en.json +++ b/lang/en.json @@ -3,6 +3,7 @@ "back": "back", "categories": "Categories", "category-info-tooltip": "Info & Map key", + "choose_filter": "Choose filter", "closed": "closed", "default": "default", "edit": "edit", @@ -16,7 +17,6 @@ "export:OSMJSON": "Download as OSM JSON", "export:OSMXML": "Download as OSM XML", "facilities": "Facilities", - "filter_results": "Filter results", "header:attributes": "Attributes", "header:export": "Export", "header:osm_meta": "OSM Meta", diff --git a/lang/es.json b/lang/es.json index 2ecbd1ea..29574399 100644 --- a/lang/es.json +++ b/lang/es.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/et.json b/lang/et.json index ed4e98e6..007fa41d 100644 --- a/lang/et.json +++ b/lang/et.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/fr.json b/lang/fr.json index ba7ff99c..f1ce4d26 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -3,6 +3,7 @@ "back": "Retour", "categories": "", "category-info-tooltip": "Info & Légende", + "choose_filter": "", "closed": "Fermé", "default": "Par défaut", "edit": "éditer", diff --git a/lang/hu.json b/lang/hu.json index 70432f29..2d3c49a6 100644 --- a/lang/hu.json +++ b/lang/hu.json @@ -3,6 +3,7 @@ "back": "Vissza", "categories": "", "category-info-tooltip": "Információk és jelmagyarázat", + "choose_filter": "", "closed": "Lezárva", "default": "Alapértelmezett", "edit": "Szerkesztés", diff --git a/lang/it.json b/lang/it.json index 67316501..6aa719f2 100644 --- a/lang/it.json +++ b/lang/it.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/ja.json b/lang/ja.json index 0117028c..8a9f09da 100644 --- a/lang/ja.json +++ b/lang/ja.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/nl.json b/lang/nl.json index 65f2c2b2..bcdfe757 100644 --- a/lang/nl.json +++ b/lang/nl.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/pl.json b/lang/pl.json index e4bf5142..ed6e7d89 100644 --- a/lang/pl.json +++ b/lang/pl.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/pt-br.json b/lang/pt-br.json index 26fecf3b..a30e82b9 100644 --- a/lang/pt-br.json +++ b/lang/pt-br.json @@ -3,6 +3,7 @@ "back": "voltar", "categories": "", "category-info-tooltip": "Info & Legenda", + "choose_filter": "", "closed": "fechado", "default": "padrão", "edit": "editar", diff --git a/lang/pt.json b/lang/pt.json index a6eb1881..1a9c34b3 100644 --- a/lang/pt.json +++ b/lang/pt.json @@ -3,6 +3,7 @@ "back": "voltar", "categories": "", "category-info-tooltip": "Info & Legenda", + "choose_filter": "", "closed": "fechado", "default": "padrão", "edit": "editar", diff --git a/lang/ro.json b/lang/ro.json index 98b3d7ca..054d9abf 100644 --- a/lang/ro.json +++ b/lang/ro.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/ru.json b/lang/ru.json index cb557569..18f7e1f2 100644 --- a/lang/ru.json +++ b/lang/ru.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/sr.json b/lang/sr.json index 409be7aa..2311a43c 100644 --- a/lang/sr.json +++ b/lang/sr.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/template.json b/lang/template.json index 943a418d..7f47ea50 100644 --- a/lang/template.json +++ b/lang/template.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/lang/uk.json b/lang/uk.json index 58d5a1e7..1e73f662 100644 --- a/lang/uk.json +++ b/lang/uk.json @@ -3,6 +3,7 @@ "back": "", "categories": "", "category-info-tooltip": "", + "choose_filter": "", "closed": "", "default": "", "edit": "", diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js index 72e122d1..ce402651 100644 --- a/src/CategoryOverpassFilter.js +++ b/src/CategoryOverpassFilter.js @@ -58,7 +58,7 @@ class CategoryOverpassFilter { this.formFilter = new form('filter-' + this.master.id, this.data, { 'type': 'form_chooser', - 'button:add_element': '-- ' + lang('filter_results') + ' --', + 'button:add_element': '-- ' + lang('choose_filter') + ' --', 'order': false } ) From 171398e0e459687708a69c8e2226a3881de70859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Tue, 8 Jan 2019 15:33:09 +0100 Subject: [PATCH 13/33] CategoryOverpassFilter: when a category has only one filter, don't let user choose --- lib/modulekit/form | 2 +- src/CategoryOverpassFilter.js | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/modulekit/form b/lib/modulekit/form index 5d39b2f6..50f1ea5e 160000 --- a/lib/modulekit/form +++ b/lib/modulekit/form @@ -1 +1 @@ -Subproject commit 5d39b2f61b7eda9a635414acaeb3c4e0dc524490 +Subproject commit 50f1ea5eb822240876ed89504e3180f9c7dcbc05 diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js index ce402651..24a9866a 100644 --- a/src/CategoryOverpassFilter.js +++ b/src/CategoryOverpassFilter.js @@ -55,13 +55,16 @@ class CategoryOverpassFilter { } } - this.formFilter = new form('filter-' + this.master.id, this.data, - { + let masterOptions = {} + if (Object.keys(this.data).length > 1) { + masterOptions = { 'type': 'form_chooser', 'button:add_element': '-- ' + lang('choose_filter') + ' --', 'order': false } - ) + } + + this.formFilter = new form('filter-' + this.master.id, this.data, masterOptions) this.formFilter.show(this.domFilter) this.formFilter.onchange = function () { let param = JSON.parse(JSON.stringify(this.formFilter.get_data())) From bd1f6388c83a5917fb15694967e7277f20106a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Tue, 8 Jan 2019 19:28:11 +0100 Subject: [PATCH 14/33] CategoryOverpassFilter: when a name of a filter value has no name use valueName or the value --- src/CategoryOverpassFilter.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js index 24a9866a..36a26f5e 100644 --- a/src/CategoryOverpassFilter.js +++ b/src/CategoryOverpassFilter.js @@ -32,8 +32,9 @@ class CategoryOverpassFilter { } if ('values' in f) { + let template = OverpassLayer.twig.twig({ data: f.valueName || '{{ value }}', autoescape: true }) + if (Array.isArray(f.values) && f.valueName) { - let template = OverpassLayer.twig.twig({ data: f.valueName, autoescape: true }) let newValues = {} f.values.forEach(value => { newValues[value] = template.render({ value }).toString() @@ -45,7 +46,9 @@ class CategoryOverpassFilter { let t = OverpassLayer.twig.twig({ data: f.values[k1], autoescape: true }) f.values[k1] = t.render({}).toString() } else if (typeof f.values[k1] === 'object') { - if (f.values[k1].name) { + if (!('name' in f.values[k1])) { + f.values[k1].name = template.render({ value: k1 }).toString() + } else if (f.values[k1].name) { let t = OverpassLayer.twig.twig({ data: f.values[k1].name, autoescape: true }) f.values[k1].name = t.render({}).toString() } From b283996183550c664d4d75d9ffa2b79b2d05985e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sun, 20 Jan 2019 17:49:08 +0100 Subject: [PATCH 15/33] Repository as separate class --- src/OpenStreetBrowserLoader.js | 21 ++++++++++++++++++++- src/Repository.js | 6 ++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/Repository.js diff --git a/src/OpenStreetBrowserLoader.js b/src/OpenStreetBrowserLoader.js index 660365e7..615540a2 100644 --- a/src/OpenStreetBrowserLoader.js +++ b/src/OpenStreetBrowserLoader.js @@ -1,9 +1,12 @@ var OverpassLayer = require('overpass-layer') +const Repository = require('./Repository') + function OpenStreetBrowserLoader () { this.types = {} this.categories = {} this.repoCache = {} + this.repositories = {} this.templates = {} this._loadClash = {} // if a category is being loaded multiple times, collect callbacks } @@ -94,7 +97,9 @@ OpenStreetBrowserLoader.prototype.getRepo = function (repo, options, callback) { this.repoCache[repo] = [ req.statusText, null ] } else { try { - this.repoCache[repo] = [ null, JSON.parse(req.responseText) ] + let repoData = JSON.parse(req.responseText) + this.repositories[repo] = new Repository(repo, repoData) + this.repoCache[repo] = [ null, repoData ] } catch (err) { console.log('couldn\'t parse repository', req.responseText) this.repoCache[repo] = [ 'couldn\t parse repository', null ] @@ -123,6 +128,20 @@ OpenStreetBrowserLoader.prototype.getRepo = function (repo, options, callback) { req.send() } +OpenStreetBrowserLoader.prototype.getRepository = function (id, options, callback) { + if (id in this.repositories) { + return callback(null, this.repositories[id]) + } + + this.getRepo(id, options, (err, repoData) => { + if (err) { + return callback(err) + } + + callback(null, this.repositories[id]) + }) +} + /** * @param string id ID of the template * @parapm [object] options Options. diff --git a/src/Repository.js b/src/Repository.js new file mode 100644 index 00000000..0f565c6f --- /dev/null +++ b/src/Repository.js @@ -0,0 +1,6 @@ +module.exports = class Repository { + constructor (id, data) { + this.id = id + this.data = data + } +} From 48648c35df08bdc9765b7576a98d109c0a504035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sun, 20 Jan 2019 20:56:05 +0100 Subject: [PATCH 16/33] Category*: pass repository as additional parameter to constructor --- src/CategoryBase.js | 3 ++- src/CategoryIndex.js | 4 ++-- src/CategoryOverpass.js | 4 ++-- src/OpenStreetBrowserLoader.js | 4 +++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/CategoryBase.js b/src/CategoryBase.js index b397a83e..27d50709 100644 --- a/src/CategoryBase.js +++ b/src/CategoryBase.js @@ -4,7 +4,7 @@ var OpenStreetBrowserLoader = require('./OpenStreetBrowserLoader') var tabs = require('modulekit-tabs') const ee = require('event-emitter') -function CategoryBase (options, data) { +function CategoryBase (options, data, repository) { if (typeof options === 'string') { this.id = options this.options = {} @@ -12,6 +12,7 @@ function CategoryBase (options, data) { this.id = options.id this.options = options } + this.repository = repository this.parentCategory = null this.childrenLoadingCount = 0 this.data = data diff --git a/src/CategoryIndex.js b/src/CategoryIndex.js index 0a44e85c..aa868371 100644 --- a/src/CategoryIndex.js +++ b/src/CategoryIndex.js @@ -5,8 +5,8 @@ var CategoryBase = require('./CategoryBase') CategoryIndex.prototype = Object.create(CategoryBase.prototype) CategoryIndex.prototype.constructor = CategoryIndex -function CategoryIndex (options, data) { - CategoryBase.call(this, options, data) +function CategoryIndex (options, data, repository) { + CategoryBase.call(this, options, data, repository) this.childrenDoms = {} this.childrenCategories = null diff --git a/src/CategoryOverpass.js b/src/CategoryOverpass.js index a2ecfc91..8f4e0207 100644 --- a/src/CategoryOverpass.js +++ b/src/CategoryOverpass.js @@ -35,10 +35,10 @@ var defaultValues = { CategoryOverpass.prototype = Object.create(CategoryBase.prototype) CategoryOverpass.prototype.constructor = CategoryOverpass -function CategoryOverpass (options, data) { +function CategoryOverpass (options, data, repository) { var p - CategoryBase.call(this, options, data) + CategoryBase.call(this, options, data, repository) data.id = this.id diff --git a/src/OpenStreetBrowserLoader.js b/src/OpenStreetBrowserLoader.js index 615540a2..ac5dd98c 100644 --- a/src/OpenStreetBrowserLoader.js +++ b/src/OpenStreetBrowserLoader.js @@ -203,9 +203,11 @@ OpenStreetBrowserLoader.prototype.getCategoryFromData = function (id, options, d return callback(new Error('unknown type'), null) } + let repository = this.repositories[ids.repositoryId] + var opt = JSON.parse(JSON.stringify(options)) opt.id = ids.id - var layer = new this.types[data.type](opt, data) + var layer = new this.types[data.type](opt, data, repository) layer.setMap(this.map) From 2e8a82fee9357292db31bbe22b5f2ac502231a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sun, 20 Jan 2019 20:57:15 +0100 Subject: [PATCH 17/33] repoTrans(): read lang from repository --- src/OpenStreetBrowserLoader.js | 1 - src/Repository.js | 2 ++ src/tagTranslations.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/OpenStreetBrowserLoader.js b/src/OpenStreetBrowserLoader.js index ac5dd98c..25aac4a4 100644 --- a/src/OpenStreetBrowserLoader.js +++ b/src/OpenStreetBrowserLoader.js @@ -61,7 +61,6 @@ OpenStreetBrowserLoader.prototype.getCategory = function (id, options, callback) this.getCategoryFromData(ids.id, opt, repoData.categories[ids.entityId], function (err, category) { if (category) { category.setMap(this.map) - category.lang = repoData.lang } callback(err, category) diff --git a/src/Repository.js b/src/Repository.js index 0f565c6f..c5e7de30 100644 --- a/src/Repository.js +++ b/src/Repository.js @@ -2,5 +2,7 @@ module.exports = class Repository { constructor (id, data) { this.id = id this.data = data + + this.lang = this.data.lang || {} } } diff --git a/src/tagTranslations.js b/src/tagTranslations.js index 9f46a828..98ed328d 100644 --- a/src/tagTranslations.js +++ b/src/tagTranslations.js @@ -26,7 +26,7 @@ OverpassLayer.twig.extendFunction('isTranslated', function (str) { return tagTranslationsIsTranslated(str) }) OverpassLayer.twig.extendFunction('repoTrans', function (str) { - let lang = global.currentCategory.lang + let lang = global.currentCategory.repository.lang return str in lang ? lang[str] : str }) From 9ef10606f44c4d9b36f2f2ccc8786be994cb2fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sun, 20 Jan 2019 20:57:38 +0100 Subject: [PATCH 18/33] CategoryOverpassFilter: before rendering filters, set global.currentCategory --- src/CategoryOverpassFilter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js index 36a26f5e..ae7f29c5 100644 --- a/src/CategoryOverpassFilter.js +++ b/src/CategoryOverpassFilter.js @@ -25,6 +25,7 @@ class CategoryOverpassFilter { for (var k in this.data) { let f = this.data[k] if ('name' in f && typeof f.name === 'string') { + global.currentCategory = this.master let t = OverpassLayer.twig.twig({ data: f.name, autoescape: true }) f.name = t.render({}).toString() } else if (!('name' in f)) { From 3eb99252316b3d5980f8ea873e795234d3c9677f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sun, 20 Jan 2019 21:56:31 +0100 Subject: [PATCH 19/33] CategoryOverpassFilter: specify values via path into data --- package.json | 3 ++- src/CategoryOverpassFilter.js | 5 +++++ src/getPathFromJSON.js | 11 +++++++++++ test/getPathFromJSON.js | 25 +++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/getPathFromJSON.js create mode 100644 test/getPathFromJSON.js diff --git a/package.json b/package.json index 257dd35f..3146a62c 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ ] }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "test": "mocha --bail", "build": "npm run build-locales && browserify -g browserify-css src/index.js -o dist/tmp1.js && babel --presets env dist/tmp1.js > dist/tmp2.js && mv dist/tmp2.js dist/openstreetbrowser.js && rm dist/tmp1.js", "build-locales": "for i in `ls locales/` ; do browserify locales/$i -o dist/locale-$i ; done", "watch": "npm run build-locales && watchify --debug -g browserify-css src/index.js -o dist/openstreetbrowser.js -v", @@ -79,6 +79,7 @@ "browserify": "^14.4.0", "browserify-css": "^0.14.0", "leaflet-polylinedecorator": "https://github.com/plepe/Leaflet.PolylineDecorator.git", + "mocha": "^5.2.0", "standard": "^10.0.2", "watchify": "^3.9.0" }, diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js index ae7f29c5..24abd4f8 100644 --- a/src/CategoryOverpassFilter.js +++ b/src/CategoryOverpassFilter.js @@ -3,6 +3,7 @@ const tabs = require('modulekit-tabs') const state = require('./state') const Filter = require('overpass-frontend').Filter +const getPathFromJSON = require('./getPathFromJSON') class CategoryOverpassFilter { constructor (master) { @@ -35,6 +36,10 @@ class CategoryOverpassFilter { if ('values' in f) { let template = OverpassLayer.twig.twig({ data: f.valueName || '{{ value }}', autoescape: true }) + if (typeof f.values === 'string') { + f.values = getPathFromJSON(f.values, this.master.data) + } + if (Array.isArray(f.values) && f.valueName) { let newValues = {} f.values.forEach(value => { diff --git a/src/getPathFromJSON.js b/src/getPathFromJSON.js new file mode 100644 index 00000000..15a6e149 --- /dev/null +++ b/src/getPathFromJSON.js @@ -0,0 +1,11 @@ +module.exports = function getPathFromJSON (path, json) { + if (typeof path === 'string') { + path = path.split(/\./) + } + + if (path.length === 0) { + return json + } + + return getPathFromJSON(path.slice(1), json[path[0]]) +} diff --git a/test/getPathFromJSON.js b/test/getPathFromJSON.js new file mode 100644 index 00000000..f4eadf6b --- /dev/null +++ b/test/getPathFromJSON.js @@ -0,0 +1,25 @@ +const getPathFromJSON = require('../src/getPathFromJSON') +const assert = require('assert') + +describe('getPathFromJSON', function () { + it('const', function () { + assert.deepEqual( + getPathFromJSON('const', { const: { 'foo': 'foo', 'bar': 'bar' } }), + { 'foo': 'foo', 'bar': 'bar' } + ) + }) + + it('const.x', function () { + assert.deepEqual( + getPathFromJSON('const.x', { const: { x: { 'foo': 'foo', 'bar': 'bar' } } }), + { 'foo': 'foo', 'bar': 'bar' } + ) + }) + + it('const.y (not exist)', function () { + assert.deepEqual( + getPathFromJSON('const.y', { const: { x: { 'foo': 'foo', 'bar': 'bar' } } }), + undefined + ) + }) +}) From 0660221803c1d78070c32e599e21e36fa073a089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sun, 20 Jan 2019 22:31:16 +0100 Subject: [PATCH 20/33] CategoryOverpassFilter: create query via twig function --- src/CategoryOverpassFilter.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js index 24abd4f8..31db4413 100644 --- a/src/CategoryOverpassFilter.js +++ b/src/CategoryOverpassFilter.js @@ -33,6 +33,10 @@ class CategoryOverpassFilter { f.name = lang('tag:' + k) } + if ('query' in f) { + f.queryTemplate = OverpassLayer.twig.twig({ data: f.query, autoescape: false }) + } + if ('values' in f) { let template = OverpassLayer.twig.twig({ data: f.valueName || '{{ value }}', autoescape: true }) @@ -105,7 +109,11 @@ class CategoryOverpassFilter { var d = this.data[k] - if ('values' in d && param[k] in d.values && typeof d.values[param[k]] === 'object' && 'query' in d.values[param[k]]) { + if (d.queryTemplate) { + let f = new Filter(d.queryTemplate.render({ value: param[k] }).toString()) + this.additionalFilter.push(f.def) + continue + } else if ('values' in d && param[k] in d.values && typeof d.values[param[k]] === 'object' && 'query' in d.values[param[k]]) { let f = new Filter(d.values[param[k]].query) this.additionalFilter.push(f.def) continue From 053c5c695aa142eca05c2203ebb72074aa577715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Wed, 23 Jan 2019 20:53:25 +0100 Subject: [PATCH 21/33] CategoryOverpassFilter: rename template to valueNameTemplate --- src/CategoryOverpassFilter.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js index 31db4413..05b4f71d 100644 --- a/src/CategoryOverpassFilter.js +++ b/src/CategoryOverpassFilter.js @@ -38,7 +38,7 @@ class CategoryOverpassFilter { } if ('values' in f) { - let template = OverpassLayer.twig.twig({ data: f.valueName || '{{ value }}', autoescape: true }) + let valueNameTemplate = OverpassLayer.twig.twig({ data: f.valueName || '{{ value }}', autoescape: true }) if (typeof f.values === 'string') { f.values = getPathFromJSON(f.values, this.master.data) @@ -47,7 +47,7 @@ class CategoryOverpassFilter { if (Array.isArray(f.values) && f.valueName) { let newValues = {} f.values.forEach(value => { - newValues[value] = template.render({ value }).toString() + newValues[value] = valueNameTemplate.render({ value }).toString() }) f.values = newValues } else if (typeof f.values === 'object') { @@ -57,7 +57,7 @@ class CategoryOverpassFilter { f.values[k1] = t.render({}).toString() } else if (typeof f.values[k1] === 'object') { if (!('name' in f.values[k1])) { - f.values[k1].name = template.render({ value: k1 }).toString() + f.values[k1].name = valueNameTemplate.render({ value: k1 }).toString() } else if (f.values[k1].name) { let t = OverpassLayer.twig.twig({ data: f.values[k1].name, autoescape: true }) f.values[k1].name = t.render({}).toString() From 1fe0623070d4f9857242ecf70594055da8efef67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Wed, 23 Jan 2019 21:32:41 +0100 Subject: [PATCH 22/33] CategoryOverpassFilter: values.query has preference to queryTemplate --- src/CategoryOverpassFilter.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js index 05b4f71d..2f4a63e9 100644 --- a/src/CategoryOverpassFilter.js +++ b/src/CategoryOverpassFilter.js @@ -109,12 +109,12 @@ class CategoryOverpassFilter { var d = this.data[k] - if (d.queryTemplate) { - let f = new Filter(d.queryTemplate.render({ value: param[k] }).toString()) + if ('values' in d && param[k] in d.values && typeof d.values[param[k]] === 'object' && 'query' in d.values[param[k]]) { + let f = new Filter(d.values[param[k]].query) this.additionalFilter.push(f.def) continue - } else if ('values' in d && param[k] in d.values && typeof d.values[param[k]] === 'object' && 'query' in d.values[param[k]]) { - let f = new Filter(d.values[param[k]].query) + } else if (d.queryTemplate) { + let f = new Filter(d.queryTemplate.render({ value: param[k] }).toString()) this.additionalFilter.push(f.def) continue } From e4f043ba514ab140bbf72584cdf73fb0c6cb777b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Thu, 24 Jan 2019 07:59:12 +0100 Subject: [PATCH 23/33] CategoryOverpassFilter: support values as twig template --- src/CategoryOverpassFilter.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js index 2f4a63e9..e2f8c949 100644 --- a/src/CategoryOverpassFilter.js +++ b/src/CategoryOverpassFilter.js @@ -41,7 +41,27 @@ class CategoryOverpassFilter { let valueNameTemplate = OverpassLayer.twig.twig({ data: f.valueName || '{{ value }}', autoescape: true }) if (typeof f.values === 'string') { - f.values = getPathFromJSON(f.values, this.master.data) + let valuesTemplate = OverpassLayer.twig.twig({ data: f.values, autoescape: true }) + let div = document.createElement('div') + div.innerHTML = valuesTemplate.render(this.master.data) + + let options = div.getElementsByTagName('option') + f.values = {} + + for (let i = 0; i < options.length; i++) { + let option = options[i] + + let k = option.value + f.values[k] = {} + + if (option.textContent) { + f.values[k].name = option.textContent + } + + if (option.hasAttribute('query')) { + f.values[k].query = option.getAttribute('query') + } + } } if (Array.isArray(f.values) && f.valueName) { From 0a727add04cfcaff83a77312e7cbf57deec86498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Thu, 24 Jan 2019 07:59:31 +0100 Subject: [PATCH 24/33] CategoryOverpassFilters: documentation --- doc/Filters.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 doc/Filters.md diff --git a/doc/Filters.md b/doc/Filters.md new file mode 100644 index 00000000..3a254e75 --- /dev/null +++ b/doc/Filters.md @@ -0,0 +1,62 @@ +Each category can define a list of filters. This is an additional JSON value with the key "filter", e.g.: + +```json +{ + "query": { + "13": "nwr[amenity]" + }, + "filter": { + "type": { + "name": "{{ keyTrans('amenity') }}", + "type": "select", + "values": { + "bar": { + "nwr[ + }, + } + } +} +``` +This defines a filter with the ID 'type' and the translated name of the key 'amenity'. It's of type 'select' and has several possible values. + +Each filter can define the following values: +* name: Name of the filter. String, which can make use of twig functions, e.g. `keyTrans` as in the above example. +* type: A form type, e.g. 'text', 'select', 'radio', 'checkbox' +* values: Possible values. Can either be an array, an object or a html string with several ` +{% endfor %} + +``` + +* Name is generated from text content. If it is empty, it can be created via `valueName`. +* Query is optional, it can be created from key (or filter id), op and the value. From d2bb8e09c6771403fc9a517630287225f6072eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sun, 27 Jan 2019 07:52:20 +0100 Subject: [PATCH 25/33] Filter: support multiple keys --- src/CategoryOverpassFilter.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/CategoryOverpassFilter.js b/src/CategoryOverpassFilter.js index e2f8c949..29d119d5 100644 --- a/src/CategoryOverpassFilter.js +++ b/src/CategoryOverpassFilter.js @@ -156,6 +156,12 @@ class CategoryOverpassFilter { } } + if (Array.isArray(v.key)) { + v = { + "or": v.key.map(key => { return [ { key, value: v.value, op: v.op } ]}) + } + } + kvFilter.push(v) } From af09ed2b469e7cb39515f5d85db78d430ba8ad7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20B=C3=B6sch-Plepelits?= Date: Sun, 27 Jan 2019 10:57:10 +0100 Subject: [PATCH 26/33] Filter: support multiple keys with wildcards --- doc/Filters.md | 2 +- src/CategoryOverpassFilter.js | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/doc/Filters.md b/doc/Filters.md index 3a254e75..516c072e 100644 --- a/doc/Filters.md +++ b/doc/Filters.md @@ -25,7 +25,7 @@ Each filter can define the following values: * values: Possible values. Can either be an array, an object or a html string with several `