Skip to content

Commit ff15676

Browse files
committed
Clean new code architecture
commit 5a25135 Author: Tom Darboux <[email protected]> Date: Sat Feb 19 05:30:38 2022 +0100 Fixes and update js linter commit 89b3b19 Author: Tom Darboux <[email protected]> Date: Sat Feb 19 05:04:56 2022 +0100 update architecture
1 parent 2c87e45 commit ff15676

18 files changed

+160
-134
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
node_modules/
2+
*.kate-swp

Diff for: README.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,21 @@ That's all, put it behind the server of your choice. For dev, I use PHP with `ph
1414

1515
## Install a search and reverse server:
1616

17-
I use ADDOK: `https://addok.readthedocs.io/en/latest/`, it's quite easy to install and works very well with french addresses.
17+
I use ADDOK: https://addok.readthedocs.io/en/latest/, it's quite easy to install and works very well with french addresses.
1818

19-
There are other. Qwant maps uses `https://github.com/CanalTP/mimirsbrunn`
19+
There are other. Qwant maps uses https://github.com/CanalTP/mimirsbrunn
2020

2121
## Serving tiles
2222

23-
For a small server, there is `https://openmaptiles.org/`. Qwant maps uses a more complex stack, see `https://github.com/Qwant/qwantmaps`
23+
For a small server, there is https://openmaptiles.org/. Qwant maps uses a more complex stack, see https://github.com/Qwant/qwantmaps
2424

2525
If you don't want to host tiles yourself, maptiler or mapbox offer hosting solutions.
2626

2727
You can use ppsfleet tiles for testing, but only for testing.
2828

2929

30+
## Dev
3031

32+
It does not need compilation.
3133

32-
33-
34-
34+
To check the code: `npm standard --fix`

Diff for: config.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
BASE_MAP_URL = 'https://maps.ppsfleet.navy/tileserver-data/qwant-basic-gl-style-toulouse/built-style-debug.json'
1+
const BASE_MAP_URL = 'https://maps.ppsfleet.navy/tileserver-data/qwant-basic-gl-style-toulouse/built-style-debug.json'
22

3-
BASE_SEARCH_URL = (query) => `https://search.maps.ppsfleet.navy/search/?q=${query}`
3+
const BASE_SEARCH_URL = (query) => `https://search.maps.ppsfleet.navy/search/?q=${query}`
44

5-
BASE_REVERSE_URL = (lat,lng) => `https://search.maps.ppsfleet.navy/reverse?lat=${lat}&lon=${lng}`
5+
const BASE_REVERSE_URL = (lat, lng) => `https://search.maps.ppsfleet.navy/reverse?lat=${lat}&lon=${lng}`

Diff for: index.php

+8-62
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<link href='https://maps.ppsfleet.navy/maplibre/mapbox-gl.css' rel='stylesheet' />
1616
<!-- css -->
1717
<link href='https://static.ppsfleet.navy/fonts/russisch-sans/style.css' rel='stylesheet' />
18-
<link href='./static/css/style.css' rel='stylesheet' />
18+
<link href='./src/css/style.css' rel='stylesheet' />
1919
<!-- config -->
2020
<script src='./config.js'></script>
2121
<style>
@@ -40,70 +40,16 @@
4040
<!-- todo: add a contextmenu -->
4141

4242
<script type="module">
43-
import { parseHashCoordinates } from './static/js/tools/parseHashCoordinates.js'
44-
import { Search } from './static/js/Search.js'
45-
import { Place } from './static/js/Place.js'
46-
import { BaseChipComponent } from './static/js/components/BaseChipComponent.js'
43+
import search from './src/singletons/search.js'
44+
import map from './src/singletons/map.js'
4745

48-
customElements.define('base-chip', BaseChipComponent)
46+
import PlaceComponent from './src/components/PlaceComponent.js'
47+
customElements.define('c-place', PlaceComponent)
4948

50-
let params = new URLSearchParams(window.location.search);
51-
const {lng, lat, zoom} = parseHashCoordinates(params.get("map") || '', 1.4436, 43.6042, 13)
52-
53-
var map = new mapboxgl.Map({
54-
container: 'map',
55-
style: BASE_MAP_URL,
56-
center: [lng, lat],
57-
zoom: zoom,
58-
});
59-
60-
var nav = new mapboxgl.NavigationControl();
61-
62-
var gps = new mapboxgl.GeolocateControl({
63-
positionOptions: {
64-
enableHighAccuracy: true
65-
},
66-
trackUserLocation: true
67-
})
68-
69-
var scale = new mapboxgl.ScaleControl({
70-
maxWidth: 80,
71-
unit: 'metric'
72-
});
73-
74-
const search = new Search(map)
75-
76-
map.addControl(nav, 'bottom-right');
77-
map.addControl(gps, 'bottom-right');
78-
map.addControl(scale);
79-
80-
map.on('load', function() {
81-
82-
});
83-
84-
map.on('contextmenu', function(e) {
85-
new Place(map, e.lngLat.lat, e.lngLat.lng)
86-
})
87-
88-
map.on('moveend', function() {
89-
const {lng, lat} = map.getCenter();
90-
const zoom = map.getZoom();
91-
const hash = `map=${zoom}/${lat}/${lng}`
92-
history.replaceState(null, null, `${document.location.pathname}?${hash}`);
93-
});
9449
</script>
9550

96-
<template id="template-base-chip">
97-
<div class="chip_delete">
98-
<img src="./static/images/breeze/edit-delete-black.svg" class="icon--medium icon--white"/>
99-
</div>
100-
<div class="chip__name">
101-
<slot name="name">empty</slot>
102-
</div>
103-
<div class="chip__actions">
104-
<slot name="actions"></slot>
105-
</div>
106-
<link href='./static/css/chip.css' rel='stylesheet' />
107-
</template>
51+
<?php
52+
include "src/components/ChipBaseTemplate.php";
53+
?>
10854
</body>
10955
</html>

Diff for: static/js/components/BaseChipComponent.js renamed to src/components/ChipBaseComponent.js

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
export class BaseChipComponent extends HTMLElement {
1+
export default class ChipBaseComponent extends HTMLElement {
22
constructor () {
33
super()
44
const template = document
5-
.getElementById('template-base-chip')
5+
.getElementById('template-chip-base')
66
.content
7-
const shadowRoot = this.attachShadow({ mode: 'open' })
7+
this.attachShadow({ mode: 'open' })
88
.appendChild(template.cloneNode(true))
99

1010
this.shadowRoot.querySelector('.chip_delete').addEventListener('click', (event) => {
@@ -16,6 +16,8 @@ export class BaseChipComponent extends HTMLElement {
1616
this.shadowRoot.dispatchEvent(deleteEvent)
1717
event.stopPropagation()
1818
})
19+
20+
this.setName(this.getAttribute('name'))
1921
}
2022

2123
static get observedAttributes () {
@@ -25,8 +27,14 @@ export class BaseChipComponent extends HTMLElement {
2527
attributeChangedCallback (name, oldValue, newValue) {
2628
switch (name) {
2729
case 'name':
28-
this.shadowRoot.querySelector('.chip__name').innerText = newValue
30+
this.setName(newValue)
2931
break
3032
}
3133
}
34+
35+
setName (name) {
36+
if (name) {
37+
this.shadowRoot.querySelector('.chip__name').innerText = name
38+
}
39+
}
3240
}

Diff for: src/components/ChipBaseTemplate.php

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<template id="template-chip-base">
2+
<div class="chip_delete">
3+
<img src="./static/images/breeze/edit-delete-black.svg" class="icon--medium icon--white"/>
4+
</div>
5+
<div class="chip__name">
6+
<slot name="name">empty</slot>
7+
</div>
8+
<div class="chip__actions">
9+
<slot name="actions"></slot>
10+
</div>
11+
<link href='./src/css/chip.css' rel='stylesheet' />
12+
</template>

Diff for: src/components/PlaceComponent.js

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import map from '../singletons/map.js'
2+
import ChipBaseComponent from './ChipBaseComponent.js'
3+
4+
export default class PlaceComponent extends ChipBaseComponent {
5+
constructor () {
6+
super()
7+
8+
this.addEventListener('delete', (e) => {
9+
this.marker.remove()
10+
this.remove()
11+
})
12+
13+
this.addEventListener('click', (e) => {
14+
map.flyTo({ center: [this._lng, this._lat], zoom: 13 })
15+
})
16+
}
17+
18+
set coordinates ({ lat, lng }) {
19+
this._lat = lat
20+
this._lng = lng
21+
this.addMarker(lat, lng)
22+
}
23+
24+
get coordinates () {
25+
return { lat: this._lat, lng: this._lng }
26+
}
27+
28+
addMarker (lat, lng) {
29+
this?.marker?.remove()
30+
this.marker = new mapboxgl.Marker()
31+
.setLngLat([lng, lat])
32+
.addTo(map)
33+
}
34+
}

Diff for: static/css/chip.css renamed to src/css/chip.css

File renamed without changes.
File renamed without changes.

Diff for: static/css/style.css renamed to src/css/style.css

File renamed without changes.

Diff for: src/singletons/map.js

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import parseHashCoordinates from '../tools/parseHashCoordinates.js'
2+
import places from './places.js'
3+
4+
class Map extends mapboxgl.Map {
5+
constructor () {
6+
console.log('Init map')
7+
const params = new URLSearchParams(window.location.search)
8+
const { lng, lat, zoom } = parseHashCoordinates(params.get('map') || '', 1.4436, 43.6042, 13)
9+
10+
super({
11+
container: 'map',
12+
style: BASE_MAP_URL,
13+
center: [lng, lat],
14+
zoom: zoom
15+
})
16+
17+
const nav = new mapboxgl.NavigationControl()
18+
19+
const gps = new mapboxgl.GeolocateControl({
20+
positionOptions: {
21+
enableHighAccuracy: true
22+
},
23+
trackUserLocation: true
24+
})
25+
26+
const scale = new mapboxgl.ScaleControl({
27+
maxWidth: 80,
28+
unit: 'metric'
29+
})
30+
31+
this.addControl(nav, 'bottom-right')
32+
this.addControl(gps, 'bottom-right')
33+
this.addControl(scale)
34+
35+
this.on('contextmenu', function (e) {
36+
places.add(e.lngLat.lat, e.lngLat.lng)
37+
})
38+
39+
this.on('moveend', function () {
40+
const { lng, lat } = map.getCenter()
41+
const zoom = map.getZoom()
42+
const hash = `map=${zoom}/${lat}/${lng}`
43+
history.replaceState(null, null, `${document.location.pathname}?${hash}`)
44+
})
45+
}
46+
}
47+
48+
const map = new Map()
49+
export default map

Diff for: src/singletons/places.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import reverseSearch from '../tools/reverseSearch.js'
2+
3+
class Places {
4+
constructor () {
5+
this.parent = document.getElementById('places')
6+
}
7+
8+
add (lat, lng, name) {
9+
const element = document.createElement('c-place')
10+
name ? element.setAttribute('name', name) : reverseSearch(lat, lng, (value) => { element.setAttribute('name', value.features[0].properties.label) })
11+
this.parent.appendChild(element)
12+
element.coordinates = { lat, lng }
13+
return element
14+
}
15+
}
16+
17+
const places = new Places()
18+
export default places

Diff for: static/js/Search.js renamed to src/singletons/search.js

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { Place } from './Place.js'
2-
import { debounce } from './tools/debounce.js'
1+
import debounce from '../tools/debounce.js'
2+
import map from './map.js'
3+
import places from './places.js'
34

45
export class Search {
5-
constructor (map) {
6+
constructor () {
67
this.lazySearch = debounce(this.search.bind(this), 300)
78

89
document.getElementById('search-input').addEventListener('input', (e) => {
@@ -14,7 +15,7 @@ export class Search {
1415
}
1516

1617
clickOnResult (result) {
17-
new Place(this.map, result.geometry.coordinates[1], result.geometry.coordinates[0], result?.properties?.label)
18+
places.add(result.geometry.coordinates[1], result.geometry.coordinates[0], result?.properties?.label)
1819
this.map.flyTo({ center: result.geometry.coordinates, zoom: 13 })
1920
this.cleanSearchResults()
2021
}
@@ -63,6 +64,8 @@ export class Search {
6364
cleanSearchResults () {
6465
document.getElementById('search-results').innerHTML = ''
6566
document.getElementById('search-input').parentNode.classList.remove('search-label--with-results')
66-
6767
}
6868
}
69+
70+
const search = new Search()
71+
export default search

Diff for: static/js/tools/debounce.js renamed to src/tools/debounce.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export function debounce (func, timeout = 300) {
1+
export default function debounce (func, timeout = 300) {
22
let timer
33
return (...args) => {
44
clearTimeout(timer)

Diff for: static/js/tools/parseHashCoordinates.js renamed to src/tools/parseHashCoordinates.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export function parseHashCoordinates (hash, defaultLng, defaultLat, defaultZoom) {
1+
export default function parseHashCoordinates (hash, defaultLng, defaultLat, defaultZoom) {
22
const coordinates = hash.replace('#map=', '').split('/')
33

44
return {

Diff for: src/tools/reverseSearch.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default function reverseSearch (lat, lng, callback) {
2+
window.fetch(BASE_REVERSE_URL(lat, lng)).then((response) => {
3+
response.json().then(callback)
4+
})
5+
}

Diff for: static/js/Place.js

-45
This file was deleted.

Diff for: todo.md

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
11
# Code organisation
22

3-
**TODO: Keep Place.js and Search.js in class ?**
4-
5-
What about just functions (as linter says "Do not use 'new' for side effects.") ?
6-
7-
If they are functions, are they tools ?
8-
93
**TODO: Find a css linter**
104

11-
125
# Features
136

147
**TODO: Itinerary**
@@ -22,3 +15,5 @@
2215
- With a backend ? random id like etherpad
2316
- In the Url ?
2417
- In the localStorage ? But it's not shareable and it's not persistent in the long-term
18+
19+
**TODO: Display information from wikipedia / wikidata**

0 commit comments

Comments
 (0)