mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-09 08:47:11 -05:00
Add places layer
This commit is contained in:
parent
8a36a69987
commit
602975eeaa
13 changed files with 476 additions and 11 deletions
141
PLACES_INTEGRATION_CHECKLIST.md
Normal file
141
PLACES_INTEGRATION_CHECKLIST.md
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
# Places Integration Checklist
|
||||
|
||||
## Files Modified:
|
||||
- ✅ `app/javascript/controllers/stat_page_controller.js` - Added PlacesManager integration
|
||||
- ✅ `app/javascript/maps/places.js` - Fixed API authentication headers
|
||||
- ✅ `app/views/stats/_month.html.erb` - Added Places button and tag filters
|
||||
- ✅ `app/views/shared/_place_creation_modal.html.erb` - Already exists
|
||||
|
||||
## What Should Appear:
|
||||
|
||||
### On Monthly Stats Page (`/stats/YYYY/MM`):
|
||||
|
||||
1. **Map Controls** (top right of map):
|
||||
- [ ] "Heatmap" button
|
||||
- [ ] "Points" button
|
||||
- [ ] **"Places" button** ← NEW!
|
||||
|
||||
2. **Below the Map**:
|
||||
- [ ] **"Filter Places by Tags"** section ← NEW!
|
||||
- [ ] Checkboxes for each tag you've created
|
||||
- [ ] Each checkbox shows: icon + name + color dot
|
||||
|
||||
## Troubleshooting Steps:
|
||||
|
||||
### Step 1: Restart Server
|
||||
```bash
|
||||
# Stop server (Ctrl+C)
|
||||
bundle exec rails server
|
||||
|
||||
# Or with Docker:
|
||||
docker-compose restart web
|
||||
```
|
||||
|
||||
### Step 2: Hard Refresh Browser
|
||||
- Mac: `Cmd + Shift + R`
|
||||
- Windows/Linux: `Ctrl + Shift + R`
|
||||
|
||||
### Step 3: Check Browser Console
|
||||
1. Open Developer Tools (F12)
|
||||
2. Go to Console tab
|
||||
3. Look for errors (red text)
|
||||
4. You should see: "StatPage controller connected"
|
||||
|
||||
### Step 4: Verify URL
|
||||
Make sure you're on a monthly stats page:
|
||||
- ✅ `/stats/2024/11` ← Correct
|
||||
- ❌ `/stats` ← Wrong (main stats index)
|
||||
- ❌ `/stats/2024` ← Wrong (yearly stats)
|
||||
|
||||
### Step 5: Check JavaScript Loading
|
||||
In browser console, type:
|
||||
```javascript
|
||||
console.log(document.querySelector('[data-controller="stat-page"]'))
|
||||
```
|
||||
Should show the element, not null.
|
||||
|
||||
### Step 6: Verify Controller Registration
|
||||
In browser console:
|
||||
```javascript
|
||||
console.log(application.controllers)
|
||||
```
|
||||
Should include "stat-page" in the list.
|
||||
|
||||
## Expected Behavior:
|
||||
|
||||
### When You Click "Places" Button:
|
||||
1. Places layer toggles on/off
|
||||
2. Button highlights when active
|
||||
3. Map shows custom markers with tag icons
|
||||
|
||||
### When You Check Tag Filters:
|
||||
1. Map updates immediately
|
||||
2. Shows only places with selected tags
|
||||
3. Unchecking all shows all places
|
||||
|
||||
## If Nothing Shows:
|
||||
|
||||
### Check if you have any places created:
|
||||
```bash
|
||||
bundle exec rails console
|
||||
|
||||
# In console:
|
||||
user = User.find_by(email: 'your@email.com')
|
||||
user.places.count # Should be > 0
|
||||
user.tags.count # Should be > 0
|
||||
```
|
||||
|
||||
### Create test data:
|
||||
```bash
|
||||
bundle exec rails console
|
||||
|
||||
user = User.first
|
||||
tag = user.tags.create!(name: "Test", icon: "📍", color: "#FF5733")
|
||||
|
||||
# Create via API or console:
|
||||
place = user.places.create!(
|
||||
name: "Test Place",
|
||||
latitude: 40.7128,
|
||||
longitude: -74.0060,
|
||||
source: :manual
|
||||
)
|
||||
place.tags << tag
|
||||
```
|
||||
|
||||
## Verification Script:
|
||||
|
||||
Run this in Rails console to verify everything:
|
||||
|
||||
```ruby
|
||||
user = User.first
|
||||
puts "Tags: #{user.tags.count}"
|
||||
puts "Places: #{user.places.count}"
|
||||
puts "Places with tags: #{user.places.joins(:tags).distinct.count}"
|
||||
|
||||
if user.tags.any?
|
||||
puts "\nYour tags:"
|
||||
user.tags.each do |tag|
|
||||
puts " #{tag.icon} #{tag.name} (#{tag.places.count} places)"
|
||||
end
|
||||
end
|
||||
|
||||
if user.places.any?
|
||||
puts "\nYour places:"
|
||||
user.places.limit(5).each do |place|
|
||||
puts " #{place.name} at (#{place.latitude}, #{place.longitude})"
|
||||
puts " Tags: #{place.tags.map(&:name).join(', ')}"
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Still Having Issues?
|
||||
|
||||
Check these files exist and have the right content:
|
||||
- `app/javascript/maps/places.js` - Should export PlacesManager class
|
||||
- `app/javascript/controllers/stat_page_controller.js` - Should import PlacesManager
|
||||
- `app/views/stats/_month.html.erb` - Should have Places button at line ~73
|
||||
|
||||
Look for JavaScript errors in browser console that might indicate:
|
||||
- Import/export issues
|
||||
- Syntax errors
|
||||
- Missing dependencies
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -37,6 +37,7 @@ import { countryCodesMap } from "../maps/country_codes";
|
|||
import { VisitsManager } from "../maps/visits";
|
||||
import { ScratchLayer } from "../maps/scratch_layer";
|
||||
import { LocationSearch } from "../maps/location_search";
|
||||
import { PlacesManager } from "../maps/places";
|
||||
|
||||
import "leaflet-draw";
|
||||
import { initializeFogCanvas, drawFogCanvas, createFogOverlay } from "../maps/fog_of_war";
|
||||
|
|
@ -213,6 +214,10 @@ export default class extends BaseController {
|
|||
// Expose visits manager globally for location search integration
|
||||
window.visitsManager = this.visitsManager;
|
||||
|
||||
// Initialize the places manager
|
||||
this.placesManager = new PlacesManager(this.map, this.apiKey);
|
||||
this.placesManager.initialize();
|
||||
|
||||
// Expose maps controller globally for family integration
|
||||
window.mapsController = this;
|
||||
|
||||
|
|
@ -258,7 +263,8 @@ export default class extends BaseController {
|
|||
Areas: this.areasLayer,
|
||||
Photos: this.photoMarkers,
|
||||
"Suggested Visits": this.visitsManager.getVisitCirclesLayer(),
|
||||
"Confirmed Visits": this.visitsManager.getConfirmedVisitCirclesLayer()
|
||||
"Confirmed Visits": this.visitsManager.getConfirmedVisitCirclesLayer(),
|
||||
"Places": this.placesManager.placesLayer
|
||||
};
|
||||
|
||||
this.layerControl = L.control.layers(this.baseMaps(), controlsLayer).addTo(this.map);
|
||||
|
|
@ -2216,5 +2222,32 @@ export default class extends BaseController {
|
|||
});
|
||||
}
|
||||
|
||||
togglePlaceCreationMode() {
|
||||
if (!this.placesManager) {
|
||||
console.warn("Places manager not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
const button = document.getElementById('create-place-btn');
|
||||
|
||||
if (this.placesManager.creationMode) {
|
||||
// Disable creation mode
|
||||
this.placesManager.disableCreationMode();
|
||||
if (button) {
|
||||
button.classList.remove('btn-error');
|
||||
button.classList.add('btn-success');
|
||||
button.title = 'Click to create a place on the map';
|
||||
}
|
||||
} else {
|
||||
// Enable creation mode
|
||||
this.placesManager.enableCreationMode();
|
||||
if (button) {
|
||||
button.classList.remove('btn-success');
|
||||
button.classList.add('btn-error');
|
||||
button.title = 'Click map to place marker (click again to cancel)';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default class extends Controller {
|
|||
try {
|
||||
const response = await fetch(
|
||||
`/api/v1/places/nearby?latitude=${latitude}&longitude=${longitude}&limit=5`,
|
||||
{ headers: { 'APIKEY': this.apiKeyValue } }
|
||||
{ headers: { 'Authorization': `Bearer ${this.apiKeyValue}` } }
|
||||
)
|
||||
|
||||
if (!response.ok) throw new Error('Failed to load nearby places')
|
||||
|
|
@ -110,7 +110,7 @@ export default class extends Controller {
|
|||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'APIKEY': this.apiKeyValue
|
||||
'Authorization': `Bearer ${this.apiKeyValue}`
|
||||
},
|
||||
body: JSON.stringify(payload)
|
||||
})
|
||||
|
|
|
|||
41
app/javascript/controllers/places_filter_controller.js
Normal file
41
app/javascript/controllers/places_filter_controller.js
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
connect() {
|
||||
console.log("Places filter controller connected");
|
||||
}
|
||||
|
||||
filterPlaces(event) {
|
||||
// Get reference to the maps controller's placesManager
|
||||
const mapsController = window.mapsController;
|
||||
if (!mapsController || !mapsController.placesManager) {
|
||||
console.warn("Maps controller or placesManager not found");
|
||||
return;
|
||||
}
|
||||
|
||||
// Collect all checked tag IDs
|
||||
const checkboxes = this.element.querySelectorAll('input[type="checkbox"][data-tag-id]');
|
||||
const selectedTagIds = Array.from(checkboxes)
|
||||
.filter(cb => cb.checked)
|
||||
.map(cb => parseInt(cb.dataset.tagId));
|
||||
|
||||
console.log("Filtering places by tags:", selectedTagIds);
|
||||
|
||||
// Filter places by selected tags (or show all if none selected)
|
||||
mapsController.placesManager.filterByTags(selectedTagIds.length > 0 ? selectedTagIds : null);
|
||||
}
|
||||
|
||||
clearAll(event) {
|
||||
event.preventDefault();
|
||||
|
||||
// Uncheck all checkboxes
|
||||
const checkboxes = this.element.querySelectorAll('input[type="checkbox"][data-tag-id]');
|
||||
checkboxes.forEach(cb => cb.checked = false);
|
||||
|
||||
// Show all places
|
||||
const mapsController = window.mapsController;
|
||||
if (mapsController && mapsController.placesManager) {
|
||||
mapsController.placesManager.filterByTags(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
import L from "leaflet";
|
||||
import "leaflet.heat";
|
||||
import { createAllMapLayers } from "../maps/layers";
|
||||
import { PlacesManager } from "../maps/places";
|
||||
import BaseController from "./base_controller";
|
||||
|
||||
export default class extends BaseController {
|
||||
static targets = ["map", "loading", "heatmapBtn", "pointsBtn"];
|
||||
static targets = ["map", "loading", "heatmapBtn", "pointsBtn", "placesBtn"];
|
||||
|
||||
connect() {
|
||||
super.connect();
|
||||
|
|
@ -64,6 +65,10 @@ export default class extends BaseController {
|
|||
this.markersLayer = L.layerGroup(); // Don't add to map initially
|
||||
this.heatmapLayer = null;
|
||||
|
||||
// Initialize Places Manager
|
||||
this.placesManager = new PlacesManager(this.map, this.apiKey);
|
||||
this.placesManager.initialize();
|
||||
|
||||
// Load data for this month
|
||||
this.loadMonthData();
|
||||
|
||||
|
|
@ -228,6 +233,40 @@ export default class extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
togglePlaces() {
|
||||
if (!this.placesManager) {
|
||||
console.warn("Places manager not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.map.hasLayer(this.placesManager.placesLayer)) {
|
||||
// Remove places layer
|
||||
this.map.removeLayer(this.placesManager.placesLayer);
|
||||
if (this.hasPlacesBtnTarget) {
|
||||
this.placesBtnTarget.classList.remove('btn-active');
|
||||
}
|
||||
} else {
|
||||
// Add places layer
|
||||
this.map.addLayer(this.placesManager.placesLayer);
|
||||
if (this.hasPlacesBtnTarget) {
|
||||
this.placesBtnTarget.classList.add('btn-active');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filterPlacesByTags(event) {
|
||||
if (!this.placesManager) return;
|
||||
|
||||
// Collect all checked tag IDs
|
||||
const checkboxes = event.currentTarget.closest('[data-controller="stat-page"]').querySelectorAll('input[type="checkbox"][data-tag-id]');
|
||||
const selectedTagIds = Array.from(checkboxes)
|
||||
.filter(cb => cb.checked)
|
||||
.map(cb => parseInt(cb.dataset.tagId));
|
||||
|
||||
// Filter places by selected tags (or show all if none selected)
|
||||
this.placesManager.filterByTags(selectedTagIds.length > 0 ? selectedTagIds : null);
|
||||
}
|
||||
|
||||
showLoading(show) {
|
||||
if (this.hasLoadingTarget) {
|
||||
this.loadingTarget.style.display = show ? 'flex' : 'none';
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export class PlacesManager {
|
|||
}
|
||||
|
||||
const response = await fetch(url, {
|
||||
headers: { 'APIKEY': this.apiKey }
|
||||
headers: { 'Authorization': `Bearer ${this.apiKey}` }
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error('Failed to load places');
|
||||
|
|
@ -171,7 +171,7 @@ export class PlacesManager {
|
|||
try {
|
||||
const response = await fetch(`/api/v1/places/${placeId}`, {
|
||||
method: 'DELETE',
|
||||
headers: { 'APIKEY': this.apiKey }
|
||||
headers: { 'Authorization': `Bearer ${this.apiKey}` }
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error('Failed to delete place');
|
||||
|
|
|
|||
|
|
@ -98,3 +98,67 @@
|
|||
</div>
|
||||
|
||||
<%= render 'map/settings_modals' %>
|
||||
|
||||
<!-- Places Control Buttons -->
|
||||
<div class="absolute top-4 left-4 z-[1001] flex flex-col gap-2">
|
||||
<!-- Create Place Button -->
|
||||
<button id="create-place-btn"
|
||||
class="btn btn-circle btn-success shadow-lg"
|
||||
onclick="window.mapsController?.togglePlaceCreationMode()"
|
||||
title="Click to create a place on the map">
|
||||
<%= icon 'map-pin-plus' %>
|
||||
</button>
|
||||
|
||||
<!-- Tag Filter Toggle Button -->
|
||||
<% if current_user.tags.any? %>
|
||||
<button class="btn btn-circle btn-primary shadow-lg"
|
||||
onclick="document.getElementById('places-tag-filter').classList.toggle('hidden')"
|
||||
title="Filter Places by Tags">
|
||||
<%#= icon 'filter' %>
|
||||
</button>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!-- Tag Filters Panel (Floating) -->
|
||||
<% if current_user.tags.any? %>
|
||||
<div id="places-tag-filter" class="absolute top-20 left-4 bg-base-100 rounded-lg shadow-xl p-4 max-w-xs z-[1000] hidden"
|
||||
data-controller="places-filter">
|
||||
<div class="flex justify-between items-center mb-3">
|
||||
<h3 class="font-semibold flex items-center gap-2">
|
||||
<%#= icon 'filter' %> Filter Places by Tags
|
||||
</h3>
|
||||
<button class="btn btn-ghost btn-xs btn-circle" onclick="document.getElementById('places-tag-filter').classList.add('hidden')">
|
||||
<%#= icon 'x' %>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2 max-h-96 overflow-y-auto">
|
||||
<% current_user.tags.ordered.each do |tag| %>
|
||||
<label class="flex items-center gap-2 cursor-pointer hover:bg-base-200 p-2 rounded-lg transition-colors">
|
||||
<input type="checkbox"
|
||||
data-tag-id="<%= tag.id %>"
|
||||
data-action="change->places-filter#filterPlaces"
|
||||
class="checkbox checkbox-sm checkbox-primary">
|
||||
<span class="text-xl"><%= tag.icon %></span>
|
||||
<span class="text-sm font-medium flex-1"><%= tag.name %></span>
|
||||
<% if tag.color.present? %>
|
||||
<span class="w-3 h-3 rounded-full" style="background-color: <%= tag.color %>;"></span>
|
||||
<% end %>
|
||||
</label>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 pt-3 border-t border-base-300">
|
||||
<button class="btn btn-sm btn-ghost w-full" data-action="click->places-filter#clearAll">
|
||||
Clear All Filters
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-2 text-xs text-base-content/70">
|
||||
<%= icon 'info', class: 'inline w-3 h-3' %> Select tags to filter places. Uncheck all to show all places.
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- Include Place Creation Modal -->
|
||||
<%= render 'shared/place_creation_modal' %>
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
<li><%= link_to 'Visits & Places<sup>α</sup>'.html_safe, visits_url(status: :confirmed), class: "#{active_class?(visits_url)}" %></li>
|
||||
<li><%= link_to 'Imports', imports_url, class: "#{active_class?(imports_url)}" %></li>
|
||||
<li><%= link_to 'Exports', exports_url, class: "#{active_class?(exports_url)}" %></li>
|
||||
<li><%= link_to 'Tags', tags_url, class: "#{active_class?(tags_url)}" %></li>
|
||||
</ul>
|
||||
</details>
|
||||
</li>
|
||||
|
|
@ -99,6 +100,7 @@
|
|||
<li><%= link_to 'Visits & Places<sup>α</sup>'.html_safe, visits_url(status: :confirmed), class: "mx-1 #{active_class?(visits_url)}" %></li>
|
||||
<li><%= link_to 'Imports', imports_url, class: "#{active_class?(imports_url)}" %></li>
|
||||
<li><%= link_to 'Exports', exports_url, class: "#{active_class?(exports_url)}" %></li>
|
||||
<li><%= link_to 'Tags', tags_url, class: "#{active_class?(tags_url)}" %></li>
|
||||
</ul>
|
||||
</details>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@
|
|||
<button class="btn btn-sm btn-outline" data-stat-page-target="pointsBtn" data-action="click->stat-page#togglePoints">
|
||||
<%= icon 'map-pin' %> Points
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline" data-stat-page-target="placesBtn" data-action="click->stat-page#togglePlaces">
|
||||
<%= icon 'map-pin-plus' %> Places
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -83,6 +86,33 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tag Filters -->
|
||||
<% if current_user.tags.any? %>
|
||||
<div class="mt-4 p-4 bg-base-200 rounded-lg">
|
||||
<h3 class="font-semibold mb-3 flex items-center gap-2">
|
||||
<%= icon 'filter' %> Filter Places by Tags
|
||||
</h3>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<% current_user.tags.ordered.each do |tag| %>
|
||||
<label class="flex items-center gap-2 cursor-pointer hover:bg-base-300 px-3 py-2 rounded-lg transition-colors">
|
||||
<input type="checkbox"
|
||||
data-tag-id="<%= tag.id %>"
|
||||
data-action="change->stat-page#filterPlacesByTags"
|
||||
class="checkbox checkbox-sm checkbox-primary">
|
||||
<span class="text-xl"><%= tag.icon %></span>
|
||||
<span class="text-sm font-medium"><%= tag.name %></span>
|
||||
<% if tag.color.present? %>
|
||||
<span class="w-3 h-3 rounded-full ml-1" style="background-color: <%= tag.color %>;"></span>
|
||||
<% end %>
|
||||
</label>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="mt-2 text-sm text-base-content/70">
|
||||
<%= icon 'info' %> Select tags to filter places on the map. Uncheck all to show all places.
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- Map Stats -->
|
||||
<!--div class="stats grid grid-cols-2 md:grid-cols-4 gap-4 mt-4">
|
||||
<div class="stat">
|
||||
|
|
@ -318,3 +348,6 @@
|
|||
|
||||
<!-- Include Sharing Modal -->
|
||||
<%= render 'shared/sharing_modal' %>
|
||||
|
||||
<!-- Include Place Creation Modal -->
|
||||
<%= render 'shared/place_creation_modal' %>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
class AddUserIdToPlaces < ActiveRecord::Migration[8.0]
|
||||
def change
|
||||
disable_ddl_transaction!
|
||||
def up
|
||||
# Add nullable for backward compatibility, will enforce later via data migration
|
||||
add_reference :places, :user, null: true, foreign_key: true, index: true
|
||||
add_reference :places, :user, null: true, index: {algorithm: :concurrently} unless foreign_key_exists?(:places, :users)
|
||||
end
|
||||
|
||||
def down
|
||||
remove_reference :places, :user, index: true if foreign_key_exists?(:places, :users)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
4
db/schema.rb
generated
4
db/schema.rb
generated
|
|
@ -316,6 +316,9 @@ ActiveRecord::Schema[8.0].define(version: 2025_11_16_134520) do
|
|||
t.datetime "updated_at", null: false
|
||||
t.geometry "path", limit: {srid: 3857, type: "line_string"}
|
||||
t.jsonb "visited_countries", default: {}, null: false
|
||||
t.uuid "sharing_uuid"
|
||||
t.jsonb "sharing_settings", default: {}
|
||||
t.index ["sharing_uuid"], name: "index_trips_on_sharing_uuid", unique: true
|
||||
t.index ["user_id"], name: "index_trips_on_user_id"
|
||||
end
|
||||
|
||||
|
|
@ -383,7 +386,6 @@ ActiveRecord::Schema[8.0].define(version: 2025_11_16_134520) do
|
|||
add_foreign_key "notifications", "users"
|
||||
add_foreign_key "place_visits", "places"
|
||||
add_foreign_key "place_visits", "visits"
|
||||
add_foreign_key "places", "users"
|
||||
add_foreign_key "points", "users"
|
||||
add_foreign_key "points", "visits"
|
||||
add_foreign_key "stats", "users"
|
||||
|
|
|
|||
105
verify_places_integration.rb
Executable file
105
verify_places_integration.rb
Executable file
|
|
@ -0,0 +1,105 @@
|
|||
# Run with: bundle exec rails runner verify_places_integration.rb
|
||||
|
||||
puts "🔍 Verifying Places Integration..."
|
||||
puts "=" * 50
|
||||
|
||||
# Check files exist
|
||||
files_to_check = [
|
||||
'app/javascript/maps/places.js',
|
||||
'app/javascript/controllers/stat_page_controller.js',
|
||||
'app/javascript/controllers/place_creation_controller.js',
|
||||
'app/views/stats/_month.html.erb',
|
||||
'app/views/shared/_place_creation_modal.html.erb'
|
||||
]
|
||||
|
||||
puts "\n📁 Checking Files:"
|
||||
files_to_check.each do |file|
|
||||
if File.exist?(file)
|
||||
puts " ✅ #{file}"
|
||||
else
|
||||
puts " ❌ MISSING: #{file}"
|
||||
end
|
||||
end
|
||||
|
||||
# Check view has our changes
|
||||
puts "\n🎨 Checking View Changes:"
|
||||
month_view = File.read('app/views/stats/_month.html.erb')
|
||||
|
||||
if month_view.include?('placesBtn')
|
||||
puts " ✅ Places button found in view"
|
||||
else
|
||||
puts " ❌ Places button NOT found in view"
|
||||
end
|
||||
|
||||
if month_view.include?('Filter Places by Tags')
|
||||
puts " ✅ Tag filter section found in view"
|
||||
else
|
||||
puts " ❌ Tag filter section NOT found in view"
|
||||
end
|
||||
|
||||
if month_view.include?('place_creation_modal')
|
||||
puts " ✅ Place creation modal included"
|
||||
else
|
||||
puts " ❌ Place creation modal NOT included"
|
||||
end
|
||||
|
||||
# Check JavaScript has our changes
|
||||
puts "\n💻 Checking JavaScript Changes:"
|
||||
controller_js = File.read('app/javascript/controllers/stat_page_controller.js')
|
||||
|
||||
if controller_js.include?('PlacesManager')
|
||||
puts " ✅ PlacesManager imported"
|
||||
else
|
||||
puts " ❌ PlacesManager NOT imported"
|
||||
end
|
||||
|
||||
if controller_js.include?('togglePlaces()')
|
||||
puts " ✅ togglePlaces() method found"
|
||||
else
|
||||
puts " ❌ togglePlaces() method NOT found"
|
||||
end
|
||||
|
||||
if controller_js.include?('filterPlacesByTags')
|
||||
puts " ✅ filterPlacesByTags() method found"
|
||||
else
|
||||
puts " ❌ filterPlacesByTags() method NOT found"
|
||||
end
|
||||
|
||||
# Check database
|
||||
puts "\n🗄️ Checking Database:"
|
||||
user = User.first
|
||||
if user
|
||||
puts " ✅ Found user: #{user.email}"
|
||||
puts " Tags: #{user.tags.count}"
|
||||
puts " Places: #{user.places.count}"
|
||||
|
||||
if user.tags.any?
|
||||
puts "\n 📌 Your Tags:"
|
||||
user.tags.limit(5).each do |tag|
|
||||
puts " #{tag.icon} #{tag.name} (#{tag.places.count} places)"
|
||||
end
|
||||
else
|
||||
puts " ⚠️ No tags created yet. Create some at /tags"
|
||||
end
|
||||
|
||||
if user.places.any?
|
||||
puts "\n 📍 Your Places:"
|
||||
user.places.limit(5).each do |place|
|
||||
puts " #{place.name} - #{place.tags.map(&:name).join(', ')}"
|
||||
end
|
||||
else
|
||||
puts " ⚠️ No places created yet. Use the API or create via console."
|
||||
end
|
||||
else
|
||||
puts " ❌ No users found"
|
||||
end
|
||||
|
||||
puts "\n" + "=" * 50
|
||||
puts "✅ Integration files are in place!"
|
||||
puts "\n📋 Next Steps:"
|
||||
puts " 1. Restart your Rails server"
|
||||
puts " 2. Hard refresh your browser (Cmd+Shift+R)"
|
||||
puts " 3. Navigate to /stats/#{Date.today.year}/#{Date.today.month}"
|
||||
puts " 4. Look for 'Places' button next to 'Heatmap' and 'Points'"
|
||||
puts " 5. Create tags at /tags if you haven't already"
|
||||
puts " 6. Create places via API with those tags"
|
||||
Loading…
Reference in a new issue