mirror of https://github.com/jlelse/GoBlog
Rework map scripts
This commit is contained in:
parent
4784bd1258
commit
921212dacf
|
@ -38,7 +38,8 @@ func Test_editorPreview(t *testing.T) {
|
|||
require.Equal(t, websocket.TextMessage, mt)
|
||||
|
||||
msgStr := string(msg)
|
||||
require.Contains(t, msgStr, "<h1>Title")
|
||||
require.Contains(t, msgStr, "<h1")
|
||||
require.Contains(t, msgStr, ">Title")
|
||||
require.Contains(t, msgStr, "<p>Content")
|
||||
require.Contains(t, msgStr, "Posts")
|
||||
|
||||
|
|
2
go.mod
2
go.mod
|
@ -43,7 +43,7 @@ require (
|
|||
github.com/paulmach/go.geojson v1.4.0
|
||||
github.com/posener/wstest v1.2.0
|
||||
github.com/pquerna/otp v1.3.0
|
||||
github.com/samber/lo v1.12.0
|
||||
github.com/samber/lo v1.13.0
|
||||
github.com/schollz/sqlite3dump v1.3.1
|
||||
github.com/snabb/sitemap v1.0.0
|
||||
github.com/spf13/cast v1.4.1
|
||||
|
|
4
go.sum
4
go.sum
|
@ -410,8 +410,8 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
|
|||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4 h1:Ha8xCaq6ln1a+R91Km45Oq6lPXj2Mla6CRJYcuV2h1w=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/samber/lo v1.12.0 h1:UZXQYR2N6FST+QWxnjV7gPmT9KkXL9eWbZxkrefVs88=
|
||||
github.com/samber/lo v1.12.0/go.mod h1:2I7tgIv8Q1SG2xEIkRq0F2i2zgxVpnyPOP0d3Gj2r+A=
|
||||
github.com/samber/lo v1.13.0 h1:82AIN+opOjdaP2pntOu8UxK1Zp0OyjJrOTMFb44YF1o=
|
||||
github.com/samber/lo v1.13.0/go.mod h1:2I7tgIv8Q1SG2xEIkRq0F2i2zgxVpnyPOP0d3Gj2r+A=
|
||||
github.com/schollz/sqlite3dump v1.3.1 h1:QXizJ7XEJ7hggjqjZ3YRtF3+javm8zKtzNByYtEkPRA=
|
||||
github.com/schollz/sqlite3dump v1.3.1/go.mod h1:mzSTjZpJH4zAb1FN3iNlhWPbbdyeBpOaTW0hukyMHyI=
|
||||
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
|
||||
|
|
13
postsDb.go
13
postsDb.go
|
@ -290,12 +290,13 @@ func (a *goBlog) undeletePost(path string) error {
|
|||
}
|
||||
|
||||
func (db *database) replacePostParam(path, param string, values []string) error {
|
||||
// Filter empty values
|
||||
values = lo.Filter(values, func(v string, _ int) bool { return v != "" })
|
||||
// Lock post creation
|
||||
db.pcm.Lock()
|
||||
defer db.pcm.Unlock()
|
||||
// Build SQL
|
||||
sqlBuilder := bufferpool.Get()
|
||||
defer bufferpool.Put(sqlBuilder)
|
||||
var sqlArgs = []any{dbNoCache}
|
||||
// Start transaction
|
||||
sqlBuilder.WriteString("begin;")
|
||||
|
@ -304,15 +305,15 @@ func (db *database) replacePostParam(path, param string, values []string) error
|
|||
sqlArgs = append(sqlArgs, path, param)
|
||||
// Insert new post parameters
|
||||
for _, value := range values {
|
||||
if value != "" {
|
||||
sqlBuilder.WriteString("insert into post_parameters (path, parameter, value) values (?, ?, ?);")
|
||||
sqlArgs = append(sqlArgs, path, param, value)
|
||||
}
|
||||
sqlBuilder.WriteString("insert into post_parameters (path, parameter, value) values (?, ?, ?);")
|
||||
sqlArgs = append(sqlArgs, path, param, value)
|
||||
}
|
||||
// Commit transaction
|
||||
sqlBuilder.WriteString("commit;")
|
||||
// Execute
|
||||
if _, err := db.exec(sqlBuilder.String(), sqlArgs...); err != nil {
|
||||
_, err := db.exec(sqlBuilder.String(), sqlArgs...)
|
||||
bufferpool.Put(sqlBuilder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Update FTS index
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -362,3 +363,34 @@ func Test_usesOfMediaFile(t *testing.T) {
|
|||
assert.Equal(t, 2, counts[0])
|
||||
}
|
||||
}
|
||||
|
||||
func Test_replaceParams(t *testing.T) {
|
||||
app := &goBlog{
|
||||
cfg: createDefaultTestConfig(t),
|
||||
}
|
||||
_ = app.initDatabase(false)
|
||||
defer app.db.close()
|
||||
|
||||
err := app.db.savePost(&post{
|
||||
Path: "/test/abc",
|
||||
Content: "ABC",
|
||||
Parameters: map[string][]string{
|
||||
"test": {
|
||||
"ABC", "DEF", "GHI",
|
||||
},
|
||||
},
|
||||
}, &postCreationOptions{new: true})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = app.db.replacePostParam("/test/abc", "test", []string{"DEF", "123", "456"})
|
||||
require.NoError(t, err)
|
||||
|
||||
p, err := app.getPost("/test/abc")
|
||||
require.NoError(t, err)
|
||||
|
||||
if assert.NotNil(t, p) {
|
||||
assert.Len(t, p.Parameters["test"], 3)
|
||||
union := lo.Union(p.Parameters["test"], []string{"DEF", "123", "456"})
|
||||
assert.Len(t, union, 3)
|
||||
}
|
||||
}
|
||||
|
|
2
queue.go
2
queue.go
|
@ -93,7 +93,7 @@ func (a *goBlog) listenOnQueue(queueName string, wait time.Duration, process que
|
|||
for !done {
|
||||
qi, err := a.peekQueue(ctx, queueName)
|
||||
if err != nil {
|
||||
log.Println("queue peek error:", err.Error())
|
||||
// log.Println("queue peek error:", err.Error())
|
||||
continue
|
||||
}
|
||||
if qi == nil {
|
||||
|
|
|
@ -1,37 +1,68 @@
|
|||
(function () {
|
||||
let mapEl = document.getElementById('map')
|
||||
let locations = (mapEl.dataset.locations == "") ? [] : JSON.parse(mapEl.dataset.locations)
|
||||
let tracks = (mapEl.dataset.tracks == "") ? [] : JSON.parse(mapEl.dataset.tracks)
|
||||
function loadMap() {
|
||||
// Get the map element
|
||||
let mapEl = document.getElementById('map')
|
||||
|
||||
let map = L.map('map', {
|
||||
minZoom: mapEl.dataset.minzoom,
|
||||
maxZoom: mapEl.dataset.maxzoom
|
||||
})
|
||||
// Read the map data
|
||||
// Map page
|
||||
let locations = !mapEl.dataset.locations ? [] : JSON.parse(mapEl.dataset.locations)
|
||||
let tracks = !mapEl.dataset.tracks ? [] : JSON.parse(mapEl.dataset.tracks)
|
||||
// Post map
|
||||
let paths = !mapEl.dataset.paths ? [] : JSON.parse(mapEl.dataset.paths)
|
||||
let points = !mapEl.dataset.points ? [] : JSON.parse(mapEl.dataset.points)
|
||||
|
||||
L.tileLayer("/-/tiles/{s}/{z}/{x}/{y}.png", {
|
||||
attribution: mapEl.dataset.attribution,
|
||||
}).addTo(map)
|
||||
// Create Leaflet map
|
||||
let map = L.map('map', {
|
||||
minZoom: mapEl.dataset.minzoom,
|
||||
maxZoom: mapEl.dataset.maxzoom
|
||||
})
|
||||
|
||||
let features = []
|
||||
// Set tile source and attribution
|
||||
L.tileLayer("/-/tiles/{s}/{z}/{x}/{y}.png", {
|
||||
attribution: mapEl.dataset.attribution,
|
||||
}).addTo(map)
|
||||
|
||||
locations.forEach(loc => {
|
||||
features.push(L.marker([loc.Lat, loc.Lon]).addTo(map).on('click', function () {
|
||||
window.open(loc.Post, '_blank').focus()
|
||||
}))
|
||||
})
|
||||
|
||||
tracks.forEach(track => {
|
||||
track.Paths.forEach(path => {
|
||||
features.push(L.polyline(path.map(point => [point.Lat, point.Lon]), { color: 'blue' }).addTo(map).on('click', function () {
|
||||
window.open(track.Post, '_blank').focus()
|
||||
// Add features to the map
|
||||
let features = []
|
||||
locations.forEach(loc => {
|
||||
features.push(L.marker([loc.Lat, loc.Lon]).addTo(map).on('click', function () {
|
||||
window.open(loc.Post, '_blank').focus()
|
||||
}))
|
||||
})
|
||||
track.Points.forEach(point => {
|
||||
features.push(L.marker([point.Lat, point.Lon]).addTo(map).on('click', function () {
|
||||
window.open(track.Post, '_blank').focus()
|
||||
}))
|
||||
tracks.forEach(track => {
|
||||
track.Paths.forEach(path => {
|
||||
features.push(L.polyline(path.map(point => [point.Lat, point.Lon]), { color: 'blue' }).addTo(map).on('click', function () {
|
||||
window.open(track.Post, '_blank').focus()
|
||||
}))
|
||||
})
|
||||
track.Points.forEach(point => {
|
||||
features.push(L.marker([point.Lat, point.Lon]).addTo(map).on('click', function () {
|
||||
window.open(track.Post, '_blank').focus()
|
||||
}))
|
||||
})
|
||||
})
|
||||
paths.forEach(path => {
|
||||
features.push(L.polyline(path.map(point => [point.Lat, point.Lon]), { color: 'blue' }).addTo(map))
|
||||
})
|
||||
points.forEach(point => {
|
||||
features.push(L.marker([point.Lat, point.Lon]).addTo(map))
|
||||
})
|
||||
})
|
||||
|
||||
map.fitBounds(L.featureGroup(features).getBounds(), { padding: [5, 5] })
|
||||
// Make the map fit the features
|
||||
map.fitBounds(L.featureGroup(features).getBounds(), { padding: [5, 5] })
|
||||
}
|
||||
|
||||
// Add Leaflet to the page
|
||||
|
||||
// CSS
|
||||
let css = document.createElement('link')
|
||||
css.rel = 'stylesheet'
|
||||
css.href = '/-/leaflet/leaflet.css'
|
||||
document.head.appendChild(css)
|
||||
|
||||
// JS
|
||||
let script = document.createElement('script')
|
||||
script.src = '/-/leaflet/leaflet.js'
|
||||
script.onload = loadMap
|
||||
document.head.appendChild(script)
|
||||
})()
|
|
@ -1,26 +0,0 @@
|
|||
(function () {
|
||||
let mapEl = document.getElementById('map')
|
||||
let paths = (mapEl.dataset.paths == "") ? [] : JSON.parse(mapEl.dataset.paths)
|
||||
let points = (mapEl.dataset.points == "") ? [] : JSON.parse(mapEl.dataset.points)
|
||||
|
||||
let map = L.map('map', {
|
||||
minZoom: mapEl.dataset.minzoom,
|
||||
maxZoom: mapEl.dataset.maxzoom
|
||||
})
|
||||
|
||||
L.tileLayer("/-/tiles/{s}/{z}/{x}/{y}.png", {
|
||||
attribution: mapEl.dataset.attribution,
|
||||
}).addTo(map)
|
||||
|
||||
let features = []
|
||||
|
||||
paths.forEach(path => {
|
||||
features.push(L.polyline(path.map(point => [point.Lat, point.Lon]), { color: 'blue' }).addTo(map))
|
||||
})
|
||||
|
||||
points.forEach(point => {
|
||||
features.push(L.marker([point.Lat, point.Lon]).addTo(map))
|
||||
})
|
||||
|
||||
map.fitBounds(L.featureGroup(features).getBounds(), { padding: [5, 5] })
|
||||
})()
|
53
ui.go
53
ui.go
|
@ -11,17 +11,14 @@ import (
|
|||
)
|
||||
|
||||
func (a *goBlog) renderEditorPreview(hb *htmlBuilder, bc *configBlog, p *post) {
|
||||
if p.RenderedTitle != "" {
|
||||
hb.writeElementOpen("h1")
|
||||
hb.writeEscaped(p.RenderedTitle)
|
||||
hb.writeElementClose("h1")
|
||||
}
|
||||
a.renderPostTitle(hb, p)
|
||||
a.renderPostMeta(hb, p, bc, "preview")
|
||||
if p.Content != "" {
|
||||
hb.writeElementOpen("div")
|
||||
a.postHtmlToWriter(hb, p, true)
|
||||
hb.writeElementClose("div")
|
||||
}
|
||||
// a.renderPostGPX(hb, p, bc)
|
||||
a.renderPostTax(hb, p, bc)
|
||||
}
|
||||
|
||||
|
@ -585,11 +582,6 @@ func (a *goBlog) renderGeoMap(hb *htmlBuilder, rd *renderData) {
|
|||
hb, rd,
|
||||
func(hb *htmlBuilder) {
|
||||
a.renderTitleTag(hb, rd.Blog, "")
|
||||
if !gmd.noLocations {
|
||||
hb.writeElementOpen("link", "rel", "stylesheet", "href", "/-/leaflet/leaflet.css")
|
||||
hb.writeElementOpen("script", "src", "/-/leaflet/leaflet.js")
|
||||
hb.writeElementClose("script")
|
||||
}
|
||||
},
|
||||
func(hb *htmlBuilder) {
|
||||
hb.writeElementOpen("main")
|
||||
|
@ -859,11 +851,6 @@ func (a *goBlog) renderPost(hb *htmlBuilder, rd *renderData) {
|
|||
if su := a.shortPostURL(p); su != "" {
|
||||
hb.writeElementOpen("link", "rel", "shortlink", "href", su)
|
||||
}
|
||||
if p.HasTrack() {
|
||||
hb.writeElementOpen("link", "rel", "stylesheet", "href", "/-/leaflet/leaflet.css")
|
||||
hb.writeElementOpen("script", "src", "/-/leaflet/leaflet.js")
|
||||
hb.writeElementClose("script")
|
||||
}
|
||||
},
|
||||
func(hb *htmlBuilder) {
|
||||
hb.writeElementOpen("main", "class", "h-entry")
|
||||
|
@ -872,11 +859,7 @@ func (a *goBlog) renderPost(hb *htmlBuilder, rd *renderData) {
|
|||
hb.writeElementOpen("data", "value", a.getFullAddress(p.Path), "class", "u-url hide")
|
||||
hb.writeElementClose("data")
|
||||
// Title
|
||||
if p.RenderedTitle != "" {
|
||||
hb.writeElementOpen("h1", "class", "p-name")
|
||||
hb.writeEscaped(p.RenderedTitle)
|
||||
hb.writeElementClose("h1")
|
||||
}
|
||||
a.renderPostTitle(hb, p)
|
||||
// Post meta
|
||||
a.renderPostMeta(hb, p, rd.Blog, "post")
|
||||
// Post actions
|
||||
|
@ -924,35 +907,7 @@ func (a *goBlog) renderPost(hb *htmlBuilder, rd *renderData) {
|
|||
hb.writeElementClose("div")
|
||||
}
|
||||
// GPS Track
|
||||
if p.HasTrack() {
|
||||
if track, err := a.getTrack(p); err == nil && track != nil && track.HasPoints {
|
||||
// Track stats
|
||||
hb.writeElementOpen("p")
|
||||
if track.Name != "" {
|
||||
hb.writeElementOpen("strong")
|
||||
hb.writeEscaped(track.Name)
|
||||
hb.writeElementClose("strong")
|
||||
hb.write(" ")
|
||||
}
|
||||
if track.Kilometers != "" {
|
||||
hb.write("🏁 ")
|
||||
hb.writeEscaped(track.Kilometers)
|
||||
hb.write(" ")
|
||||
hb.writeEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "kilometers"))
|
||||
hb.write(" ")
|
||||
}
|
||||
if track.Hours != "" {
|
||||
hb.write("⏱ ")
|
||||
hb.writeEscaped(track.Hours)
|
||||
}
|
||||
hb.writeElementClose("p")
|
||||
// Map
|
||||
hb.writeElementOpen("div", "id", "map", "class", "p", "data-paths", track.PathsJSON, "data-points", track.PointsJSON, "data-minzoom", track.MinZoom, "data-maxzoom", track.MaxZoom, "data-attribution", track.MapAttribution)
|
||||
hb.writeElementClose("div")
|
||||
hb.writeElementOpen("script", "defer", "", "src", a.assetFileName("js/geotrack.js"))
|
||||
hb.writeElementClose("script")
|
||||
}
|
||||
}
|
||||
a.renderPostGPX(hb, p, rd.Blog)
|
||||
// Taxonomies
|
||||
a.renderPostTax(hb, p, rd.Blog)
|
||||
hb.writeElementClose("article")
|
||||
|
|
|
@ -415,3 +415,53 @@ func (a *goBlog) renderPagination(hb *htmlBuilder, blog *configBlog, hasPrev, ha
|
|||
hb.writeElementClose("p")
|
||||
}
|
||||
}
|
||||
|
||||
func (*goBlog) renderPostTitle(hb *htmlBuilder, p *post) {
|
||||
if p == nil || p.RenderedTitle == "" {
|
||||
return
|
||||
}
|
||||
hb.writeElementOpen("h1", "class", "p-name")
|
||||
hb.writeEscaped(p.RenderedTitle)
|
||||
hb.writeElementClose("h1")
|
||||
}
|
||||
|
||||
func (a *goBlog) renderPostGPX(hb *htmlBuilder, p *post, b *configBlog) {
|
||||
if p == nil || !p.HasTrack() {
|
||||
return
|
||||
}
|
||||
track, err := a.getTrack(p)
|
||||
if err != nil || track == nil || !track.HasPoints {
|
||||
return
|
||||
}
|
||||
// Track stats
|
||||
hb.writeElementOpen("p")
|
||||
if track.Name != "" {
|
||||
hb.writeElementOpen("strong")
|
||||
hb.writeEscaped(track.Name)
|
||||
hb.writeElementClose("strong")
|
||||
hb.write(" ")
|
||||
}
|
||||
if track.Kilometers != "" {
|
||||
hb.write("🏁 ")
|
||||
hb.writeEscaped(track.Kilometers)
|
||||
hb.write(" ")
|
||||
hb.writeEscaped(a.ts.GetTemplateStringVariant(b.Lang, "kilometers"))
|
||||
hb.write(" ")
|
||||
}
|
||||
if track.Hours != "" {
|
||||
hb.write("⏱ ")
|
||||
hb.writeEscaped(track.Hours)
|
||||
}
|
||||
hb.writeElementClose("p")
|
||||
// Map
|
||||
hb.writeElementOpen(
|
||||
"div", "id", "map", "class", "p",
|
||||
"data-paths", track.PathsJSON,
|
||||
"data-points", track.PointsJSON,
|
||||
"data-minzoom", track.MinZoom, "data-maxzoom", track.MaxZoom,
|
||||
"data-attribution", track.MapAttribution,
|
||||
)
|
||||
hb.writeElementClose("div")
|
||||
hb.writeElementOpen("script", "defer", "", "src", a.assetFileName("js/geomap.js"))
|
||||
hb.writeElementClose("script")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue