Skip to content

Commit

Permalink
Merge 2b8ecf2 into b6aaa15
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeCohen committed Mar 17, 2024
2 parents b6aaa15 + 2b8ecf2 commit e232bd6
Show file tree
Hide file tree
Showing 24 changed files with 607 additions and 122 deletions.
4 changes: 4 additions & 0 deletions app/assets/stylesheets/mo/_content.scss
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,7 @@ ul.tight-list {
font-size: 13px;
font-weight: bold;
}

.btn-constraint-warning {
color: black;
}
4 changes: 4 additions & 0 deletions app/assets/stylesheets/mo/_utilities.scss
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,10 @@
text-indent: 0;
}

.violation-highlight {
background-color: orange;
}

//
// larger devices
// --------------------------------------------------
Expand Down
57 changes: 57 additions & 0 deletions app/controllers/projects/violations_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

# Show and remove non-compliant Observations from a Project
module Projects
# Actions
# -------
# edit (get)
# update (patch)
#
class ViolationsController < ApplicationController
before_action :login_required
before_action :pass_query_params

def update
unless (@project = find_or_goto_index(Project, params[:project_id]))
return
end

params[:project]&.each do |key, value|
next unless key =~ /|remove_\d+$/ && value == "1"

obs_id = key.sub("remove_", "")
remove_observation_if_permitted(obs_id)
end

redirect_with_query(project_path(@project))
end

#########

private

def default_index_subaction
list_all
end

def list_all
return unless find_project!

@violations = @project.violations
end

def find_project!
@project = find_or_goto_index(Project, params[:project_id])
end

def remove_observation_if_permitted(obs_id)
return unless (obs = Observation.safe_find(obs_id))
return unless @project.observations.include?(obs)

permitted_removers = @project.admin_group_user_ids + [obs.user_id]
return unless permitted_removers.include?(User.current.id)

@project.remove_observations([obs])
end
end
end
2 changes: 0 additions & 2 deletions app/controllers/projects_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ def show
return unless find_project_and_where!

set_ivars_for_show
check_constraint_violations
end

##############################################################################
Expand Down Expand Up @@ -204,7 +203,6 @@ def pattern
if pattern.match(/^\d+$/) &&
(@project = Project.safe_find(pattern))
set_ivars_for_show
check_constraint_violations
render("show", location: project_path(@project.id))
else
query = create_query(:Project, :pattern_search, pattern: pattern)
Expand Down
8 changes: 0 additions & 8 deletions app/controllers/projects_controller/validators.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,4 @@ def valid_dates
flash_error(:add_project_ends_before_start.t)
false
end

def check_constraint_violations
count = @project.count_violations
return unless count.positive? && @is_admin

flash_warning(:show_project_violation_count.t(count: count,
id: @project.id))
end
end
106 changes: 106 additions & 0 deletions app/helpers/projects_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# frozen_string_literal: true

# View Helpers for Projects, Project Violations
module ProjectsHelper
def violation_table_headers(project)
[
nil, # column for checkbox
"#{:CONSTRAINTS.l}:",
"#{:DATES.l}: #{project.date_range}",
"Lat: #{project.location.north} to #{project.location.south}",
"Lon: #{project.location.west} to #{project.location.east} ",
location_link(project.location.display_name, project.location,
nil, false),
nil # column for observation.user
]
end

def violation_table_rows(form:, project:, violations:)
violations.each_with_object([]) do |obs, rows|
rows << [
violation_checkbox(form: form, project: project, obs: obs),
link_to_object(obs, obs.text_name) + " (#{obs.id})",
styled_obs_when(project, obs),
styled_obs_lat(project, obs),
styled_obs_long(project, obs),
styled_obs_where(project, obs),
user_link(obs.user)
]
end
end

def violations_help_text(project)
:form_violations_help.l if project.violations_removable_by_current_user?
end

def violations_submit_text(project)
if project.violations_removable_by_current_user?
:form_violations_remove_selected.l
else
:form_violations_show_project.l
end
end

#########

private

def violation_checkbox(form:, project:, obs:)
if violation_checkbox_viewers(project, obs).include?(User.current.id)
form.check_box("remove_#{obs.id}")
end
end

def violation_checkbox_viewers(project, obs)
project.admin_group_user_ids + [obs.user_id]
end

def styled_obs_when(project, obs)
if project.violates_date_range?(obs)
tag.span(obs.when, class: "violation-highlight")
else
obs.when
end
end

def styled_obs_lat(project, obs)
return "" if obs.lat.blank?

displayed_coord =
coord_or_hidden(obs: obs, project: project, coord: obs.lat)
return displayed_coord if project.location.contains_lat?(obs.lat)

tag.span(displayed_coord, class: "violation-highlight")
end

def styled_obs_long(project, obs)
return "" if obs.long.blank?

displayed_coord =
coord_or_hidden(obs: obs, project: project, coord: obs.long)

return displayed_coord if project.location.contains_long?(obs.long)

tag.span(displayed_coord, class: "violation-highlight")
end

def coord_or_hidden(obs:, project:, coord:)
if !obs.gps_hidden? ||
User.current == obs.user ||
project.trusted_by?(User.current) && project.admin?(User.current)
coord
else
:hidden.l
end
end

def styled_obs_where(project, obs)
if obs.lat.present? || # If lat/lon present, ignore Location for compliance
project.location.found_here?(obs)
location_link(obs.place_name, obs.location, nil, false)
else
tag.span(location_link(obs.place_name, obs.location, nil, false),
class: "violation-highlight")
end
end
end
12 changes: 0 additions & 12 deletions app/helpers/table_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,4 @@ def make_row(row, args)
def make_td(cell, args)
tag.td(**args[:cell_opts]) { cell.to_s }
end

# ?
# def make_line(cell_opts)
# colspan = cell_opts[:colspan]
# if colspan
# tag.tr(class: "MatrixLine") do
# tag.td(tag.hr, class: "MatrixLine", colspan: colspan)
# end
# else
# safe_empty
# end
# end
end
13 changes: 10 additions & 3 deletions app/models/location.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@
# parse_longitude:: Validate and parse longitude from a string.
# parse_altitude:: Validate and parse altitude from a string.
# found_here?:: Was the given obs found here?
# contains?(lt, ln):: Does Location contain the given latititude and longitude
# contains_lat?
# contains_long?
#
# ==== Name methods
# display_name:: +name+ reformated based on user's preference.
Expand Down Expand Up @@ -296,11 +299,15 @@ def found_here?(obs)
end

def contains?(lat, long)
(lat <= north) && (lat >= south) && contains_longitude(long)
contains_lat?(lat) && contains_long?(long)
end

def contains_longitude(long)
return (long >= west) && (long <= east) if west <= east
def contains_lat?(lat)
(south..north).cover?(lat)
end

def contains_long?(long)
return (west...east).cover?(long) if west <= east

(long >= west) || (long <= east)
end
Expand Down
58 changes: 29 additions & 29 deletions app/models/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
# title:: Title string.
# summary:: Summary of purpose.
# open_membership Enable users to add themselves, disable shared editing
# location::
# image::
# start_date:: start date or nil
# end_date:: end date or nil
#
# == Methods
#
Expand All @@ -29,8 +33,9 @@
# current?:: Project (based on dates) has started and hasn't ended
# user_can_add_observation?:: Can user add observation to this Project
# violates_constraints?:: Does a given obs violate the Project constraints
# text_name:: Alias for +title+ for debugging.
# Proj.can_edit?:: Check if User has permission to edit an Obs/Image/etc.
# count_violations # of project Observations which violate constraints
# text_name:: Alias for +title+ for debugging.
# Proj.can_edit?:: Check if User has permission to edit an Obs/Image/etc.
# Proj.admin_power?:: Check for admin for a project of this Obs
#
# ==== Logging
Expand Down Expand Up @@ -379,6 +384,18 @@ def name_count
Checklist::ForProject.new(self).num_taxa
end

def violations
out_of_range_observations.to_a.union(out_of_area_observations)
end

# Is at least one violation removable by the current user?
def violations_removable_by_current_user?
user_ids = violations.map(&:user_id)
return false unless user_ids.any?

admin_group_user_ids.union(user_ids).include?(User.current_id)
end

##############################################################################
#
# :section: queries re related Observations
Expand Down Expand Up @@ -426,6 +443,16 @@ def violates_constraints?(observation)
violates_date_range?(observation)
end

def violates_location?(observation)
return false if location.blank?

!location.found_here?(observation)
end

def violates_date_range?(observation)
!(start_date..end_date).cover?(observation.when)
end

private ###############################

def obs_geoloc_outside_project_location
Expand All @@ -444,31 +471,4 @@ def obs_without_geoloc_location_not_contained_in_location
invert_where
)
end

def violates_location?(observation)
return false if location.blank?

!location.found_here?(observation)
end

def violates_date_range?(observation)
excluded_from_date_range?(observation)
end

def excluded_from_date_range?(observation)
!included_in_date_range?(observation)
end

def included_in_date_range?(observation)
starts_no_later_than?(observation) &&
ends_no_earlier_than?(observation)
end

def starts_no_later_than?(observation)
!start_date&.after?(observation.when)
end

def ends_no_earlier_than?(observation)
!end_date&.before?(observation.when)
end
end
2 changes: 1 addition & 1 deletion app/models/project/date.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def current?
def date_range(format = "%Y-%m-%d")
return :form_projects_any.l unless start_date.present? && end_date.present?

"#{start_date.strftime(format)} - #{end_date.strftime(format)}"
"#{start_date.strftime(format)} to #{end_date.strftime(format)}"
end

####################################################################
Expand Down
Loading

0 comments on commit e232bd6

Please sign in to comment.