Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# If you want, you can run:
# $ docker-compose up redis postgres
# $ docker compose up redis postgres
# $ bin/rails s
REDIS_URL=redis://@127.0.0.1:6379/1
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/
Expand Down
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,6 @@ gem "cssbundling-rails", "~> 1.1"
# Aborts requests that are taking too long.
# Set the timeout by setting the RACK_TIMEOUT_SERVICE_TIMEOUT env var
gem "rack-timeout"

gem "groupdate"

3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ GEM
geocoder (1.8.2)
globalid (1.1.0)
activesupport (>= 5.0)
groupdate (6.4.0)
activesupport (>= 6.1)
hotwire-rails (0.1.3)
rails (>= 6.0.0)
stimulus-rails
Expand Down Expand Up @@ -365,6 +367,7 @@ DEPENDENCIES
faker (~> 2.17.0)
geo_coord
geocoder (~> 1.6)
groupdate
haversine!
hotwire-rails
inline_svg
Expand Down
34 changes: 30 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,38 @@ Once you have installed and configured Ruby on Rails please fork the [linkvan-ap
To execute the app on your computer proceed as follows:

1. cd `< directory where you cloned the project repository to >`
2. Update your database configuration on `config/database.yml`
3. bundle install
4. rails db:create (to create a database)
2. Start a postgres database locally, for example with docker:
```
docker run --name linkvan_postgres -e POSTGRES_PASSWORD=mysecretpassword -p 5432:5432 -d postgres
```
3. Update your database configuration on `config/database.yml`. Based on the previous command, the updated development and test section could for example be:
```
development:
<<: *default
database: linkvan_api_development
host: localhost
port: 5432
username: postgres
password: mysecretpassword

test:
<<: *default
database: linkvan_api_test
host: localhost
port: 5432
username: postgres
password: mysecretpassword
```
4. Run `bundle install`. You might need to use [rvm](https://rvm.io/).
5. rails db:create (to create a database)
5. rails db:migrate
6. rails db:seed
7. rails fake_data:all
6. rails server
7. load http://localhost:3000/admin/dashboard on your web browser.
8. load http://localhost:3000/admin/dashboard on your web browser.
9. login with:
name: "admin@example.com",
password: "password",


## Contributing to linkvan-web
Expand Down
63 changes: 61 additions & 2 deletions app/controllers/admin/dashboard_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,65 @@
# frozen_string_literal: true
require 'json'

class Admin::DashboardController < Admin::BaseController
def index
end
end

# https://guides.rubyonrails.org/active_record_querying.html#retrieving-objects-from-the-database
def timeseries
impressions = Analytics::Visit.all
visits_per_day = impressions.group_by_day(:created_at).count

visits_per_day = visits_per_day.map do |date, count|
{
date: date.strftime('%Y-%m-%d'),
count: count
}
end

render json: visits_per_day.to_json
end
def heatmap
data = {}
# /admin/dashboard/heatmap?service=shelter
if heatmap_params[:service].present?
# Filter events by service
# service = Service.find_by(key: heatmap_params[:service])
# events = Analytics::Event.joins(impressions: :impressionables).where(impressionables: service.facilities)
else
events = Analytics::Event.all
end

events.find_each do |event|
lat = event.lat
long = event.long

key = [lat, long]
data[key] ||= { lat: lat, long: long, count: 0 }
data[key][:count] += 1
end

geojson_data = {
type: 'FeatureCollection',
features: data.values.map do |value|
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [value[:long], value[:lat]]
},
properties: {
count: value[:count]
}
}
end
}

render json: geojson_data.to_json
end

private

def heatmap_params
params.permit(:service,:format)
end
end
63 changes: 63 additions & 0 deletions app/javascript/controllers/chart_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Controller } from "@hotwired/stimulus"
import * as echarts from 'echarts';


// To connect use: data-controller="chart"
export default class extends Controller {
connect() {
console.log("Chart connect...")

fetch('/admin/dashboard/timeseries')
.then(response => response.json())
.then(data => {
console.log("data", data)

this.element.Chart = echarts.init(this.element);

let option;

option = {
dataset: {
source: data
},
xAxis: {
type: 'category',
boundaryGap: false,
},
yAxis: {
type: 'value'
},
series: [
{
type: 'line',
showSymbol: false,
encode: {
x: 'date',
y: 'pred'
}
},
{
type: 'scatter',
encode: {
x: 'date',
y: 'actual'
}
}
]
};

option && this.element.Chart.setOption(option);

})
.catch(error => {
console.error(error);
});

}

rsz(event){
console.log("Resizing chart...");
this.element.Chart.resize();
}
};

14 changes: 10 additions & 4 deletions app/javascript/controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,20 @@

import { application } from "./application"

import AutoSubmitController from "./auto_submit_controller.js"
import AutoSubmitController from "./auto_submit_controller"
application.register("auto-submit", AutoSubmitController)

import HelloController from "./hello_controller.js"
import ChartController from "./chart_controller"
application.register("chart", ChartController)

import MapController from "./map_controller"
application.register("map", MapController)

import HelloController from "./hello_controller"
application.register("hello", HelloController)

import ModalController from "./modal_controller.js"
import ModalController from "./modal_controller"
application.register("modal", ModalController)

import PagyController from "./pagy_controller.js"
import PagyController from "./pagy_controller"
application.register("pagy", PagyController)
54 changes: 54 additions & 0 deletions app/javascript/controllers/map_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Controller } from "@hotwired/stimulus"
import Map from 'ol/Map.js';
import OSM from 'ol/source/OSM.js';
import { useGeographic } from 'ol/proj';
import TileLayer from 'ol/layer/Tile.js';
import View from 'ol/View.js';
import { Heatmap as HeatmapLayer, Vector as VectorLayer } from 'ol/layer.js';
import { Vector as VectorSource } from 'ol/source.js';
import { GeoJSON } from 'ol/format.js';

useGeographic();

export default class extends Controller {
connect() {
console.log("Map connect...");

let points;

fetch('/admin/dashboard/heatmap')
.then(response => response.json())
.then(data => {
points = data;

const heatLayer = new HeatmapLayer({
title: "HeatMap",
source: new VectorSource({
features: new GeoJSON().readFeatures(points,{
dataProjection: 'EPSG:4326',
featureProjection: "EPSG:3857"
}
),
})
});

const map = new Map({
target: "map",
layers: [
new TileLayer({
source: new OSM(),
}),
heatLayer,
],
view: new View({
center: [-123.11782250644546, 49.28062873449969],
zoom: 13,
}),
});
})
.catch(error => {
console.error(error);
});
}

}
1 change: 1 addition & 0 deletions app/models/analytics/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class Analytics::Event < ApplicationRecord
belongs_to :visit

has_many :impressions, dependent: :destroy
has_many :impressionables, through: :impressions, source: :impressionable
has_many :facilities, through: :impressions,
source: :impressionable,
source_type: "Facility"
Expand Down
45 changes: 33 additions & 12 deletions app/views/admin/dashboard/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,17 +1,38 @@
<!-- Main container -->
<nav class="level">
<!-- Left side -->
<div class="level-left">
<div class="level-item">
<div class="columns">
<div class="column">
<div class="box">
<div data-controller="chart" data-action="resize@window->chart#rsz" class="inner-box"></div>
</div>
<div class="level-item">
</div>
<div class="column">
<div class="box relative" id="map-container">
<div data-controller="map" class="inner-box" id="map"></div>
</div>
</div>

<!-- Right side -->
<div class="level-right">
<p class="level-item"><a class="button">Facilities CSV</a></p>
<p class="level-item"><a class="button">Users CSV</a></p>
</div>
<div class="columns">
<div class="column">
<div class="box">
<p>Tile 3</p>
</div>
</div>
</nav>
<div class="column">
<div class="box">
<p>Tile 4</p>
</div>
</div>
</div>

<style>
.inner-box {
min-height: 500px;
width: 100%;
}

#map {
width: 100%;
height: 500px;
margin: 0;
position: block;
}
</style>
2 changes: 1 addition & 1 deletion bin/docker/bash
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
set -e

docker-compose run --rm web bash
docker compose run --rm web bash
2 changes: 1 addition & 1 deletion bin/docker/bundle
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
set -e

exec docker-compose --rm web bundle "$@"
exec docker compose --rm web bundle "$@"
2 changes: 1 addition & 1 deletion bin/docker/dev_reset
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def system!(*args)
end

def docked!(*args)
system!("docker-compose run -rm web", *args)
system!("docker compose run -rm web", *args)
end

FileUtils.chdir APP_ROOT do
Expand Down
2 changes: 1 addition & 1 deletion bin/docker/run
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
# Little helper to run a command from the docker container
set -e

exec docker-compose run --rm web "$@"
exec docker compose run --rm web "$@"
6 changes: 3 additions & 3 deletions bin/docker/setup
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def system!(*args)
end

def docked!(*args)
command_line = ["docker-compose run --rm web"] + args
command_line = ["docker compose run --rm web"] + args
system!(command_line.join(" "))
end

Expand All @@ -19,10 +19,10 @@ FileUtils.chdir APP_ROOT do
FileUtils.cp ".env.template", ".env" unless File.exist?(".env")

puts "== Pulling Images =="
system! "docker-compose pull"
system! "docker compose pull"

puts "== Building Container =="
system! "docker-compose build"
system! "docker compose build"

puts "== Running: bin/setup #{ARGV.join(' ')} =="
docked!("./bin/setup", ARGV)
Expand Down
Loading