mirror of
https://github.com/publiclab/mapknitter.git
synced 2025-12-05 16:00:00 +01:00
* Configurations update for rails 4.0 * ActiveSupport::Testing::Performance extracted to a gem * ruby prof required as a dependency * disable rubocop on bin folder * http patch * Comment out to allow testing * no longer supports plugin loading * lock to sprockets 2.12 * Active record patches * remove deprecated test syntax * fix failing tests * change new super class * replace right_aws with right_aws_api right_aws is no longer maintained, was throwing an error * lock to rails 4.2.11.1 * change rails version in install script * remove deprecation warnings * Change test lib to minitest, add minitest reporters * make app work * active record find patches * root_in_json include defaulted to false * confirm option removed in link helper * cookies serializer changed to hybrid * Change render :text to :plain render :text will be deprecated and poses a security risk * console for dev web * Check and fix interface functionality * fix export functionality * add protected attributes for the warpable model * fix image upload * Fix comments and images failing tests * include mass assignment security in annotations * render html for update images * clear mail array before every test * Fix codeclimate issues * skip failing test The test is failing because of different names in model(warpable) and controller(images) skipping this for now until we decide if we want to standardize the names * replace unprotected redirects * Fix codeclimate issues * Autofixing rubocop offenses and Problematic test for #578 (#667) * Autofixing rubocop offenses * Adding Rubocop to Travis pipelines and development branch * Fixing maps controller test * Fixing remaining offenses * change post test to create since action new is a get action * remove unprotected redirects * Fix codeclimate issues * Add yarn * Remove error log * Fix oauth icons * Modify package.json * Add yarn install to start.sh * Add leaflet google * Remove leaflet-google from package json * remove passenger error logs * Fix install script * Remove flag * Fix gemfile.lock * Fix gemfile.lock * Fix login * Upgrade Gemfile to Rails 5.0 * require rake' * Change config files * Add application record * Bump mysql * Local builds for Travis runners (#672) * Using local mysql for travis * Fix codeclimate issues * Refactoring yamls * Autofixing rubocop offenses and Problematic test for #578 (#667) * Autofixing rubocop offenses * Adding Rubocop to Travis pipelines and development branch * Fixing maps controller test * Fixing remaining offenses * Fixing unit tests * Adding docker build to travis pipelines * Adding docker build to travis pipelines * Staging builds in travis * fix travis.yml * Upgrading sintax of assets and using required gems * Using updated version of GDAL and installing required dependencies * Enabling cache in between builds * Test yarn for travis * Conditionalize rake db:setup for travis * Add semicolon * Remove comment * modify database.yml * Migrate seperately * Run create only for production * Locking newer Rails v * Running update task * Adding missing bootsnap gem * Fixing missing database * Adding missing listen gem * Fixing schema example version * Fixing migration versions * Updating dependencies for Rails 5 * Adding ApplicationMailer abstraction * Adding required initializers * Prefer require_relative instead of full path * Making associations not required by default * Regenerating schema file * Hotfixing MassAssigment * Upgrade web-console, remove mysql adapter override * Remove attr_accessible * Add rails-controller-testing gem * Follow new syntax for tests * Remove extra web-console from gemfile * Regenerating lock file * Fixing rubocop offenses and bundler version * Using correct Paperclip class as in https://github.com/rails/rails/issues/26404#issuecomment-502129936 * Fix images functional tests * images controller test typecast to string * Fix rails logger * Fix map tests * Bumping rubocop version * Autofixing rubocop offenses * Including performance cop to rubocop * Refactoring deprecated routing and secret_token * Fixing routes for feed controller * Using correct routes for RSS builder * Fixing missing routes * Fixing travis bundler and yarn cache * Fixing bundle path * Splitting bundle and yarn verifications * Autofixing rubocop offenses * Fixing prod host for travis, private class usage and rubocop offenses * Upgrade to Rails 5.2 (#685) * Upgrade Gemfile to Rails 5.0 * require rake' * Change config files * Add application record * Bump mysql * Locking newer Rails v * Running update task * Adding missing bootsnap gem * Fixing missing database * Adding missing listen gem * Fixing schema example version * Fixing migration versions * Updating dependencies for Rails 5 * Adding ApplicationMailer abstraction * Adding required initializers * Prefer require_relative instead of full path * Making associations not required by default * Regenerating schema file * Hotfixing MassAssigment * Upgrade web-console, remove mysql adapter override * Remove attr_accessible * Add rails-controller-testing gem * Follow new syntax for tests * Remove extra web-console from gemfile * Regenerating lock file * Fixing rubocop offenses and bundler version * Using correct Paperclip class as in https://github.com/rails/rails/issues/26404#issuecomment-502129936 * Fix images functional tests * images controller test typecast to string * Fix rails logger * Fix map tests * Bumping rubocop version * Autofixing rubocop offenses * Including performance cop to rubocop * Refactoring deprecated routing and secret_token * Fixing routes for feed controller * Using correct routes for RSS builder * Fixing missing routes * Fixing travis bundler and yarn cache * Fixing bundle path * Splitting bundle and yarn verifications * Fixing prod host for travis, private class usage and rubocop offenses * Enforcing params usage on get method * Using correct folder names to Rails >5 conventions * Enforcing params wrapping and adding missing front_ui route * Precompiling assets before serving * Improving Jenkins startup script * WIP action cable setup * basic action cable setup complete * minor change * minor changes * few changes * Using supported docker yaml version by Jenkins * Adding task to check database existance * Improving start script * Improving Makefile's recipes and target * Adding task to check database existance * Improving start script * Improving Makefile's recipes and target * Improving Makefile's recipes and target * Patching https://github.com/publiclab/mapknitter/pull/803 * Improving Jenkins setup * initial working functionality complete * Fix map loading * h * Fixing Leaflet-Environmental-Layers map loading * h * leaflet * fix * change * updates * stop precompiling assets * precompile * Using correct Yarn, NPM and Node version, avoiding mismatch * Removing unwanted tags.js invocation * Improving Makefile recipe * Using node_modules/ as dependencies folder, since https://github.com/sass/node-sass/issues/2050#issuecomment-317233552 * Upgrading Yarn dependencies * Removing duplicate rubocop directive * Removing test/ from codeclimate checks * Removing fixed FIXME comments * Removing fixed FIXME comments * Updating docs in README * Refactoring code * Bumping recaptcha and include methods * Adding Foreman gem * Scheduling Puma and Passenger servers * WIP action cable setup * basic action cable setup complete * minor change * minor changes * few changes * initial working functionality complete * Refactoring code * Adding Foreman gem * Scheduling Puma and Passenger servers * few minor fix * added a few tests * Refactoring connection module * Fixing migration version * Using strong params in requests * Using strong params in requests * Use Rack::Test::UploadedFile instead of ActionDispatch::Http::UploadedFile * added documentation * added more docs * added tests * Fix minor asset issue * Remove manual asset references and add them to application js * Fix asset ordering in application.js * Configure System tests (#936) * Add new system tests and fix minor asset loading * modify test * Add chromedriver to travis * Add sudo * Add dependencies to dockerfile * Properly installing chrome and chromedriver * Using puma as dependency and correct image controller * added a few tests * a few changes * remove unnecessary render * few test fixes * action cable setup (#805) * WIP action cable setup * basic action cable setup complete * minor change * minor changes * few changes * initial working functionality complete * Refactoring code * Adding Foreman gem * Scheduling Puma and Passenger servers * WIP action cable setup * basic action cable setup complete * minor change * minor changes * few changes * initial working functionality complete * Refactoring code * Adding Foreman gem * Scheduling Puma and Passenger servers * few minor fix * added a few tests * Refactoring connection module * Using strong params in requests * added documentation * added more docs * added tests * Using puma as dependency and correct image controller * added a few tests * a few changes * remove unnecessary render * few test fixes * Fixing CodeClimate issues * Synch editing add ons (#957) * few bug fixes * separate editing channels for different maps * test fixes * rubocop fixes * Undoing unwanted pattern set by Rubocop
283 lines
7.8 KiB
Ruby
Executable File
283 lines
7.8 KiB
Ruby
Executable File
class Map < ApplicationRecord
|
|
include ActiveModel::Validations
|
|
extend FriendlyId
|
|
friendly_id :name, use: %i(slugged static)
|
|
|
|
attr_accessor :image_urls
|
|
|
|
validates_presence_of :name, :slug, :author, :lat, :lon
|
|
validates_uniqueness_of :slug
|
|
validates_presence_of :location, message: ' cannot be found. Try entering a latitude and longitude if this problem persists.'
|
|
# validates_format_of :slug,
|
|
# :with => /^[\w-]*$/,
|
|
# :message => " must not include spaces and must be alphanumeric, as it'll be used in the URL of your map, like: https://mapknitter.org/maps/your-map-name. You may use dashes and underscores.",
|
|
# :on => :create
|
|
# validates_format_of :tile_url, :with => /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
|
|
validates_with NotAtOriginValidator
|
|
validates :lat, :lon, NotAtOrigin: true
|
|
|
|
has_many :exports, dependent: :destroy
|
|
has_many :tags, dependent: :destroy
|
|
has_many :comments, dependent: :destroy
|
|
has_many :annotations, dependent: :destroy
|
|
belongs_to :user, optional: true
|
|
|
|
has_many :warpables
|
|
scope :active, -> { where(archived: false) }
|
|
scope :has_user, -> { where('user_id != ?', 0) }
|
|
|
|
def validate
|
|
lat >= -90 && lat <= 90 && lon >= -180 && lat <= 180 if name != 'untitled'
|
|
end
|
|
|
|
# Hash the password before saving the record.
|
|
def before_create
|
|
self.password = Password.update(password) if password != ""
|
|
end
|
|
|
|
def placed_warpables
|
|
warpables.where('width > 0 AND nodes <> ""')
|
|
end
|
|
|
|
def private
|
|
password != ""
|
|
end
|
|
|
|
def anonymous?
|
|
author == "" || user_id.zero?
|
|
end
|
|
|
|
def self.anonymous
|
|
Map.where(user_id: 0)
|
|
end
|
|
|
|
def self.bbox(minlat, minlon, maxlat, maxlon, tag = nil)
|
|
if tag.nil?
|
|
Map.where(['lat > ? AND lat < ? AND lon > ? AND lon < ?',
|
|
minlat, maxlat, minlon, maxlon])
|
|
else
|
|
Map.where(['lat > ? AND lat < ? AND lon > ? AND lon < ?',
|
|
minlat, maxlat, minlon, maxlon])
|
|
.joins(:tags).where("tags.name = ?", tag)
|
|
end
|
|
end
|
|
|
|
def exporting?
|
|
export&.running?
|
|
end
|
|
|
|
def export
|
|
latest_export
|
|
end
|
|
|
|
def latest_export
|
|
exports.last
|
|
end
|
|
|
|
def self.authors(limit = 50)
|
|
Map.where(archived: false, password: '')
|
|
.limit(limit)
|
|
.order("maps.id DESC")
|
|
.collect(&:author)
|
|
end
|
|
|
|
def self.search(query)
|
|
query = query.squeeze(' ').strip
|
|
Map.active
|
|
.where(['author LIKE ? OR name LIKE ?
|
|
OR location LIKE ? OR description LIKE ?',
|
|
"%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%"])
|
|
end
|
|
|
|
def self.featured
|
|
Map.joins(:warpables)
|
|
.select('maps.*, count(maps.id) as image_count')
|
|
.group('warpables.map_id')
|
|
.order('image_count DESC')
|
|
end
|
|
|
|
def self.new_maps
|
|
Map.where(['password = "" AND archived = "false"'])
|
|
.order('created_at DESC')
|
|
.limit(12)
|
|
end
|
|
|
|
def self.map
|
|
Map.where(archived: false, password: '')
|
|
.select('author, maps.name, lat, lon, slug, archived, password,
|
|
users.login as user_login')
|
|
.joins(:warpables, :user)
|
|
.group('maps.id')
|
|
end
|
|
|
|
def self.featured_authors
|
|
maps = Map.active.has_user
|
|
|
|
author_counts = maps.select('user_id, author, count(1) as maps_count')
|
|
.group('author')
|
|
.order('maps_count DESC')
|
|
|
|
author_counts.map do |a|
|
|
user = User.find(a.user_id)
|
|
{ user: user, count: a.maps_count, location: user.maps.first.location }
|
|
end
|
|
end
|
|
|
|
def self.maps_nearby(lat:, lon:, dist:)
|
|
Map.active
|
|
.where(['lat>? AND lat<? AND lon>? AND lon<?',
|
|
lat - dist, lat + dist, lon - dist, lon + dist])
|
|
end
|
|
|
|
def nodes
|
|
nodes = {}
|
|
warpables.each do |warpable|
|
|
if warpable.nodes
|
|
w_nodes = []
|
|
warpable.nodes.split(',').each do |node|
|
|
node_obj = Node.find(node)
|
|
w_nodes << [node_obj.lon, node_obj.lat]
|
|
end
|
|
nodes[warpable.id.to_s] = w_nodes
|
|
end
|
|
nodes[warpable.id.to_s] ||= 'none'
|
|
end
|
|
nodes
|
|
end
|
|
|
|
# find all other maps within <dist> degrees lat or lon
|
|
def nearby_maps(dist)
|
|
return [] if lat.to_f == 0.0 || lon.to_f == 0.0
|
|
|
|
Map.where('id != ? AND lat > ? AND lat < ? AND lon > ? AND lon < ?',
|
|
id, lat - dist, lat + dist, lon - dist, lon + dist)
|
|
.limit(10)
|
|
end
|
|
|
|
def average_scale
|
|
# determine optimal zoom level
|
|
puts '> calculating scale'
|
|
pxperms = []
|
|
placed_warpables.each do |warpable|
|
|
pxperms << 100.00 / warpable.cm_per_pixel if warpable.placed?
|
|
end
|
|
average = (pxperms.inject { |sum, n| sum + n }) / pxperms.length
|
|
average
|
|
end
|
|
|
|
def best_cm_per_pixel
|
|
hist = images_histogram
|
|
scores = []
|
|
(0..(hist.length - 1)).each do |i|
|
|
scores[i] = 0
|
|
scores[i] += hist[i - 3] if i > 3
|
|
scores[i] += hist[i - 2] if i > 2
|
|
scores[i] += hist[i - 1] if i > 1
|
|
scores[i] += hist[i]
|
|
scores[i] += hist[i + 1] if i < hist.length - 2
|
|
scores[i] += hist[i + 2] if i < hist.length - 3
|
|
scores[i] += hist[i + 3] if i < hist.length - 4
|
|
end
|
|
highest = 0
|
|
scores.each_with_index { |s, i| highest = i if s > scores[highest] }
|
|
highest
|
|
end
|
|
|
|
def average_cm_per_pixel
|
|
if !warpables.empty?
|
|
scales = []
|
|
count = 0
|
|
average = 0
|
|
placed_warpables.each do |warpable|
|
|
count += 1
|
|
res = warpable.cm_per_pixel
|
|
res = 1 if res.zero? # let's not ever try to go for infinite resolution
|
|
scales << res unless res.nil?
|
|
end
|
|
total_sum = (scales.inject { |sum, n| sum + n }) if scales
|
|
average = total_sum / count if total_sum
|
|
average
|
|
else
|
|
0
|
|
end
|
|
end
|
|
|
|
# for sparklines graph display
|
|
def images_histogram
|
|
hist = []
|
|
warpables.each do |warpable|
|
|
res = warpable.cm_per_pixel.to_i
|
|
hist[res] = 0 if hist[res].nil?
|
|
hist[res] += 1
|
|
end
|
|
(0..hist.length - 1).each do |bin|
|
|
hist[bin] = 0 if hist[bin].nil?
|
|
end
|
|
hist
|
|
end
|
|
|
|
# for sparklines graph display
|
|
def grouped_images_histogram(binsize)
|
|
hist = []
|
|
warpables.each do |warpable|
|
|
res = warpable.cm_per_pixel
|
|
next if res.nil?
|
|
|
|
res = (warpable.cm_per_pixel / (0.001 + binsize)).to_i
|
|
hist[res] = 0 if hist[res].nil?
|
|
hist[res] += 1
|
|
end
|
|
(0..hist.length - 1).each do |bin|
|
|
hist[bin] = 0 if hist[bin].nil?
|
|
end
|
|
hist
|
|
end
|
|
|
|
# we'll eventually replace this with a JavaScript call to initiate an external export process:
|
|
def run_export(user, resolution)
|
|
key = APP_CONFIG ? APP_CONFIG["google_maps_api_key"] : "AIzaSyAOLUQngEmJv0_zcG1xkGq-CXIPpLQY8iQ"
|
|
|
|
new_export = Export.new(map_id: id) unless export
|
|
|
|
Exporter.run_export(user,
|
|
resolution,
|
|
export || new_export,
|
|
id,
|
|
slug,
|
|
Rails.root.to_s,
|
|
average_scale,
|
|
placed_warpables,
|
|
key)
|
|
end
|
|
|
|
def after_create
|
|
puts 'saving Map'
|
|
return unless Map.find_by_name(slug, order: "version DESC")
|
|
|
|
self.version = last.version + 1
|
|
end
|
|
|
|
def license_link
|
|
if license == "cc-by"
|
|
"<a href='http://creativecommons.org/licenses/by/3.0/'>Creative Commons Attribution 3.0 Unported License</a>"
|
|
elsif license == "publicdomain"
|
|
"<a href='http://creativecommons.org/publicdomain/zero/1.0/'>Public Domain</a>"
|
|
end
|
|
end
|
|
|
|
def has_tag(tagname)
|
|
!Tag.where(map_id: id, name: tagname).empty?
|
|
end
|
|
|
|
def add_tag(tagname, user)
|
|
tagname = tagname.downcase
|
|
tags.create(name: tagname, user_id: user.id, map_id: id) unless has_tag(tagname)
|
|
end
|
|
|
|
def fetch_map_data
|
|
# fetches a list of updated warpables along with their corners in a json format.
|
|
data = warpables
|
|
data.to_json
|
|
end
|
|
end
|