Add notes to places and manage place tags

This commit is contained in:
Eugene Burmakin 2025-11-18 22:16:34 +01:00
parent c711bed383
commit 2ab24201c1
7 changed files with 78 additions and 11 deletions

View file

@ -21,6 +21,10 @@ OIDC_REDIRECT_URI=https://your-dawarich-url.com/users/auth/openid_connect/callba
- Support for KML file uploads. #350
- Added a commented line in the `docker-compose.yml` file to use an alternative PostGIS image for ARM architecture.
- User can now create a place directly from the map and add tags and notes to it. If reverse geocoding is enabled, list of nearby places will be shown as suggestions.
- User can create and manage tags for places.
- [ ] Tags can be added when creating or editing a place.
- User can enable or disable places layers on the map to show/hide all or just some of their places based on tags.
## Fixed

View file

@ -75,7 +75,7 @@ module Api
end
def place_params
params.require(:place).permit(:name, :latitude, :longitude, :source)
params.require(:place).permit(:name, :latitude, :longitude, :source, :note)
end
def tag_ids
@ -102,6 +102,7 @@ module Api
latitude: place.latitude,
longitude: place.longitude,
source: place.source,
note: place.note,
icon: place.tags.first&.icon,
color: place.tags.first&.color,
visits_count: place.visits.count,

View file

@ -143,6 +143,7 @@ export class PlacesManager {
<div class="place-popup" style="min-width: 200px;">
<h3 class="font-bold text-lg mb-2">${place.name}</h3>
${tags ? `<div class="mb-2">${tags}</div>` : ''}
${place.note ? `<p class="text-sm text-gray-600 mb-2 italic">${this.escapeHtml(place.note)}</p>` : ''}
${place.visits_count ? `<p class="text-sm">Visits: ${place.visits_count}</p>` : ''}
<div class="mt-2 flex gap-2">
<button class="btn btn-xs btn-error" data-place-id="${place.id}" data-action="delete-place">
@ -153,6 +154,12 @@ export class PlacesManager {
`;
}
escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
setupMapClickHandler() {
this.map.on('click', (e) => {
if (this.creationMode) {

View file

@ -47,12 +47,46 @@ export class PrivacyZoneManager {
filterPoints(points) {
if (!this.zones || this.zones.length === 0) return points;
return points.filter(point => {
// Point format: [lat, lng, ...]
// Filter points and ensure polylines break at privacy zone boundaries
// We need to manipulate timestamps to force polyline breaks
const filteredPoints = [];
let lastWasPrivate = false;
let privacyZoneEncountered = false;
for (let i = 0; i < points.length; i++) {
const point = points[i];
const lat = point[0];
const lng = point[1];
return !this.isPointInPrivacyZone(lat, lng);
});
const isPrivate = this.isPointInPrivacyZone(lat, lng);
if (!isPrivate) {
// Point is not in privacy zone, include it
const newPoint = [...point]; // Clone the point array
// If we just exited a privacy zone, force a polyline break by adding
// a large time gap that exceeds minutes_between_routes threshold
if (privacyZoneEncountered && filteredPoints.length > 0) {
// Add 2 hours (120 minutes) to timestamp to force a break
// This is larger than default minutes_between_routes (30 min)
const lastPoint = filteredPoints[filteredPoints.length - 1];
if (newPoint[4]) { // If timestamp exists (index 4)
newPoint[4] = lastPoint[4] + (120 * 60); // Add 120 minutes in seconds
}
privacyZoneEncountered = false;
}
filteredPoints.push(newPoint);
lastWasPrivate = false;
} else {
// Point is in privacy zone - skip it
if (!lastWasPrivate) {
privacyZoneEncountered = true;
}
lastWasPrivate = true;
}
}
return filteredPoints;
}
filterTracks(tracks) {

View file

@ -25,15 +25,30 @@
<label class="label">
<span class="label-text font-semibold">Place Name *</span>
</label>
<input
type="text"
name="name"
placeholder="Enter place name..."
class="input input-bordered w-full"
<input
type="text"
name="name"
placeholder="Enter place name..."
class="input input-bordered w-full"
data-place-creation-target="nameInput"
required>
</div>
<div class="form-control">
<label class="label">
<span class="label-text font-semibold">Note</span>
</label>
<textarea
name="note"
placeholder="Add a personal note about this place..."
class="textarea textarea-bordered w-full bg-base-100"
rows="3"
data-place-creation-target="noteInput"></textarea>
<label class="label">
<span class="label-text-alt">Optional - Add any notes or details about this place</span>
</label>
</div>
<div class="form-control">
<label class="label">
<span class="label-text font-semibold">Tags</span>

View file

@ -0,0 +1,5 @@
class AddNoteToPlaces < ActiveRecord::Migration[8.0]
def change
add_column :places, :note, :text
end
end

3
db/schema.rb generated
View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2025_11_18_204141) do
ActiveRecord::Schema[8.0].define(version: 2025_11_18_210506) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
enable_extension "postgis"
@ -181,6 +181,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_11_18_204141) do
t.datetime "updated_at", null: false
t.geography "lonlat", limit: {srid: 4326, type: "st_point", geographic: true}
t.bigint "user_id"
t.text "note"
t.index "(((geodata -> 'properties'::text) ->> 'osm_id'::text))", name: "index_places_on_geodata_osm_id"
t.index ["lonlat"], name: "index_places_on_lonlat", using: :gist
t.index ["user_id"], name: "index_places_on_user_id"