diff --git a/editor_test.go b/editor_test.go index ec1ae68..f0fc2a3 100644 --- a/editor_test.go +++ b/editor_test.go @@ -38,7 +38,8 @@ func Test_editorPreview(t *testing.T) { require.Equal(t, websocket.TextMessage, mt) msgStr := string(msg) - require.Contains(t, msgStr, "

Title") + require.Contains(t, msgStr, "Title") require.Contains(t, msgStr, "

Content") require.Contains(t, msgStr, "Posts") diff --git a/go.mod b/go.mod index 72e0ac2..aacc560 100644 --- a/go.mod +++ b/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 diff --git a/go.sum b/go.sum index beb5eb8..b4fac66 100644 --- a/go.sum +++ b/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= diff --git a/postsDb.go b/postsDb.go index abf2c1e..de40538 100644 --- a/postsDb.go +++ b/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 diff --git a/postsDb_test.go b/postsDb_test.go index 4767cc5..5d58b0f 100644 --- a/postsDb_test.go +++ b/postsDb_test.go @@ -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) + } +} diff --git a/queue.go b/queue.go index f9c5be2..46fe0a0 100644 --- a/queue.go +++ b/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 { diff --git a/templates/assets/js/geomap.js b/templates/assets/js/geomap.js index 0038f31..5812408 100644 --- a/templates/assets/js/geomap.js +++ b/templates/assets/js/geomap.js @@ -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) })() \ No newline at end of file diff --git a/templates/assets/js/geotrack.js b/templates/assets/js/geotrack.js deleted file mode 100644 index 7e3f890..0000000 --- a/templates/assets/js/geotrack.js +++ /dev/null @@ -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] }) -})() \ No newline at end of file diff --git a/ui.go b/ui.go index 770a8fd..5249af7 100644 --- a/ui.go +++ b/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") diff --git a/uiComponents.go b/uiComponents.go index a9fd574..eb2d68b 100644 --- a/uiComponents.go +++ b/uiComponents.go @@ -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") +}