Skip to content

feat: Adds Legal Agreements object for dynamic agreements #429

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Dec 11, 2020
Merged
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@

# macOS
.DS_Store

# Redis
dump.rdb
3 changes: 3 additions & 0 deletions app/assets/stylesheets/forms/_forms.sass
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ $form-spacing-horizontal: 9px
.section-title
margin: 12px 0 5px

#disclaimer.alert
border: 2px solid var(--alert--border)

fieldset
margin: 25px 0 0
border: 1px solid #aaa
Expand Down
66 changes: 66 additions & 0 deletions app/controllers/manage/agreements_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
class Manage::AgreementsController < Manage::ApplicationController
before_action :require_director
before_action :set_agreement, only: [:show, :edit, :update, :destroy]

respond_to :html, :json

# GET /agreements
def index
@agreements = Agreement.all
end

# GET /agreements/new
def new
@agreement = Agreement.new
end

# GET /agreements/1/edit
def edit
end

# POST /agreements
def create
if !agreement_params['agreement_url'].start_with?('http://', 'https://')
flash[:alert] = "Agreement URL must start with http:// or https://"
redirect_to new_manage_agreement_path
else
@agreement = Agreement.new(agreement_params)
@agreement.save
flash[:notice] = "#{@agreement.name} was successfully created."
redirect_to manage_agreements_path
end
end

# PATCH/PUT /agreements/1
def update
if !agreement_params['agreement_url'].nil? && !agreement_params['agreement_url'].start_with?('http://', 'https://')
flash[:alert] = "Agreement URL must start with http:// or https://"
redirect_to edit_manage_agreement_url
else
@agreement.update_attributes(agreement_params)
flash[:notice] = nil
redirect_to manage_agreements_path
end
end

# DELETE /agreements/1
def destroy
@agreement.destroy
flash[:notice] = 'Agreement was successfully destroyed.'
respond_with(:manage, @agreement, location: manage_agreements_path)
end

private

# Use callbacks to share common setup or constraints between actions.
def set_agreement
@agreement = Agreement.find(params[:id])
end

# Only allow a trusted parameter "white list" through.
def agreement_params
params.require(:agreement).permit(
:name, :agreement_url
)
end
end
1 change: 1 addition & 0 deletions app/controllers/manage/checkins_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def datatable
end

def show
@agreements = Agreement.all
respond_with(:manage, @questionnaire)
end

Expand Down
8 changes: 4 additions & 4 deletions app/controllers/manage/questionnaires_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def datatable
end

def show
@agreements = Agreement.all
respond_with(:manage, @questionnaire)
end

Expand Down Expand Up @@ -70,7 +71,7 @@ def check_in
index_redirect_path = redirect_to_checkins ? manage_checkins_path : manage_questionnaires_path
if params[:check_in] == "true"
if params[:questionnaire]
q_params = params.require(:questionnaire).permit(:agreement_accepted, :phone, :can_share_info, :email)
q_params = params.require(:questionnaire).permit(:phone, :can_share_info, :email)
email = q_params.delete(:email)
@questionnaire.update_attributes(q_params)
@questionnaire.user.update_attributes(email: email)
Expand Down Expand Up @@ -153,9 +154,8 @@ def questionnaire_params
:email, :experience, :gender,
:date_of_birth, :interest, :school_id, :school_name, :major, :level_of_study,
:shirt_size, :dietary_restrictions, :special_needs, :international,
:portfolio_url, :vcs_url, :agreement_accepted, :bus_captain_interest,
:phone, :can_share_info, :code_of_conduct_accepted,
:travel_not_from_school, :travel_location, :data_sharing_accepted,
:portfolio_url, :vcs_url, :bus_captain_interest, :phone, :can_share_info,
:travel_not_from_school, :travel_location,
:graduation_year, :race_ethnicity, :resume, :delete_resume, :why_attend,
:bus_list_id, :is_bus_captain, :boarded_bus
)
Expand Down
12 changes: 7 additions & 5 deletions app/controllers/questionnaires_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def new
return redirect_to questionnaires_path
end
@questionnaire = Questionnaire.new
@agreements = Agreement.all

if session["devise.provider_data"] && session["devise.provider_data"]["info"]
info = session["devise.provider_data"]["info"]
Expand All @@ -50,6 +51,7 @@ def new

# GET /apply/edit
def edit
@agreements = Agreement.all
end

# POST /apply
Expand All @@ -62,6 +64,7 @@ def create

@questionnaire = Questionnaire.new(convert_school_name_to_id(questionnaire_params))
@questionnaire.user_id = current_user.id
@agreements = Agreement.all

respond_to do |format|
if @questionnaire.save
Expand All @@ -86,7 +89,7 @@ def update
format.html { redirect_to questionnaires_path, notice: 'Application was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.html { redirect_to edit_questionnaires_url }
format.json { render json: @questionnaire.errors, status: :unprocessable_entity }
end
end
Expand Down Expand Up @@ -126,10 +129,9 @@ def questionnaire_params
:email, :experience, :gender,
:date_of_birth, :interest, :school_id, :school_name, :major, :level_of_study,
:shirt_size, :dietary_restrictions, :special_needs, :international,
:portfolio_url, :vcs_url, :agreement_accepted, :bus_captain_interest,
:phone, :can_share_info, :code_of_conduct_accepted,
:travel_not_from_school, :travel_location, :data_sharing_accepted,
:graduation_year, :race_ethnicity, :resume, :delete_resume, :why_attend
:portfolio_url, :vcs_url, :bus_captain_interest,
:phone, :can_share_info, :travel_not_from_school, :travel_location,
:graduation_year, :race_ethnicity, :resume, :delete_resume, :why_attend, agreement_ids: []
)
end

Expand Down
2 changes: 1 addition & 1 deletion app/controllers/rsvps_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def update
bus = @questionnaire.bus_list_id
acc_status = @questionnaire.acc_status

unless @questionnaire.update_attributes(params.require(:questionnaire).permit(:agreement_accepted, :phone))
unless @questionnaire.update_attributes(params.require(:questionnaire).permit(:phone))
flash[:alert] = @questionnaire.errors.full_messages.join(", ")
redirect_to rsvp_path
return
Expand Down
13 changes: 13 additions & 0 deletions app/models/agreement.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Agreement < ApplicationRecord
include ActionView::Helpers::UrlHelper
validates_presence_of :name
validates_presence_of :agreement_url

strip_attributes

has_and_belongs_to_many :questionnaires

def formatted_agreement
"I read and accept the&nbsp;#{link_to name, agreement_url, target: '_blank'}&nbsp;agreement.".html_safe
end
end
26 changes: 23 additions & 3 deletions app/models/questionnaire.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ class Questionnaire < ApplicationRecord
belongs_to :user
belongs_to :school
belongs_to :bus_list, optional: true
has_and_belongs_to_many :agreements

validates_uniqueness_of :user_id

validates_presence_of :phone, :date_of_birth, :school_id, :experience, :shirt_size, :interest
validates_presence_of :gender, :major, :level_of_study, :graduation_year, :race_ethnicity
validates_presence_of :agreement_accepted, message: "Please read & accept"
validates_presence_of :code_of_conduct_accepted, message: "Please read & accept"
validates_presence_of :data_sharing_accepted, message: "Please read & accept"

DIETARY_SPECIAL_NEEDS_MAX_LENGTH = 500
validates_length_of :dietary_restrictions, maximum: DIETARY_SPECIAL_NEEDS_MAX_LENGTH
validates_length_of :special_needs, maximum: DIETARY_SPECIAL_NEEDS_MAX_LENGTH

validate :agreements_present

# if HackathonManager.field_enabled?(:why_attend)
# validates_presence_of :why_attend
# end
Expand Down Expand Up @@ -215,6 +215,26 @@ def verbal_status
end
end

def agreements_present
if (Agreement.all - agreements).any?
errors.add(:agreements, "must be accepted.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screen Shot 2020-12-11 at 2 17 59 AM

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this no longer works haha #437

end
end

def all_agreements_accepted?
(Agreement.all - agreements).empty?
end

def unaccepted_agreements
Agreement.all - agreements
end

def as_json(options = {})
result = super
result['all_agreements_accepted'] = all_agreements_accepted?
result
end

private

def clean_for_non_rsvp
Expand Down
10 changes: 10 additions & 0 deletions app/views/application/_unaccepted_agreements_notice.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.alert#disclaimer
%h1.section-title
%span.emphasized.fa.fa-exclamation-circle
Missing
%span.emphasized Agreements
%p
You have unaccepted agreements. You will not be allowed at #{HackathonConfig['name']} until all agreements have been accepted. Please
%strong
#{link_to "edit your application", edit_questionnaires_path}
and review all agreements before attending.
3 changes: 0 additions & 3 deletions app/views/doorkeeper/applications/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
= t(:name, scope: 'doorkeeper.applications.index')
%th
= t(:callback_url, scope: 'doorkeeper.applications.index')
%th
= t(:confidential, scope: 'doorkeeper.applications.index')


%tbody
Expand All @@ -26,4 +24,3 @@
= simple_format(application.redirect_uri)
%td
= application.confidential? ? t('doorkeeper.applications.index.confidentiality.yes') : t('doorkeeper.applications.index.confidentiality.no')

4 changes: 4 additions & 0 deletions app/views/layouts/manage/application.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@
= active_link_to manage_users_path, class: "nav-link" do
.fa.fa-users.fa-fw.icon-space-r-half
= t(:title, scope: 'pages.manage.users')
%li.nav-item
= active_link_to manage_agreements_path, class: "nav-link" do
.fa.fa-balance-scale.fa-fw.icon-space-r-half
= t(:title, scope: 'pages.manage.agreements')
%li.nav-item
= active_link_to manage_configs_path, class: "nav-link" do
.fa.fa-wrench.fa-fw.icon-space-r-half
Expand Down
10 changes: 10 additions & 0 deletions app/views/manage/agreements/_form.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.form-container
= bs_horizontal_simple_form_for(@agreement, url: url_for(action: @agreement.new_record? ? "create" : "update", controller: "agreements")) do |f|
= f.error_notification

.form-inputs
= f.input :name
= f.input :agreement_url, hint: "Should be a full https:// URL to a web page or .pdf file", label: t(:agreement_url, scope: 'pages.manage.agreements')

.form-actions
= f.button :submit, class: 'btn-primary'
3 changes: 3 additions & 0 deletions app/views/manage/agreements/edit.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
= render "layouts/manage/page_title", title: t(:edit, scope: 'pages.manage.agreements')

= render 'form'
28 changes: 28 additions & 0 deletions app/views/manage/agreements/index.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
= render "layouts/manage/page_title", title: t(:title, scope: 'pages.manage.agreements') do
= link_to "New Agreement", new_manage_agreement_path, class: "btn btn-sm btn-outline-secondary"

%p.text-muted
= t(:notice, scope: 'pages.manage.agreements', hackathon_name: HackathonConfig['name'])
.mb-4
%table.table.table-striped.table-hover
%thead
%tr
%th
%th
%th
= t(:name, scope: 'pages.manage.agreements')
%th
= t(:agreement_url, scope: 'pages.manage.agreements')

%tbody
- @agreements.each do |agreement|
%tr
%td
= link_to '<i class="fa fa-pencil"></i>'.html_safe, edit_manage_agreement_path(agreement)
%td
= link_to '<i class="fa fa-trash"></i>'.html_safe, manage_agreement_path(agreement), method: :delete, data: { confirm: "Are you sure? The agreement will be permanently deleted. This action is irreversible." }
%td
%strong
= agreement.name
%td
= agreement.agreement_url
3 changes: 3 additions & 0 deletions app/views/manage/agreements/new.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
= render "layouts/manage/page_title", title: t(:new, scope: 'pages.manage.agreements')

= render 'form'
21 changes: 12 additions & 9 deletions app/views/manage/questionnaires/_checkin_compliance_card.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,15 @@
%li.list-group-item.list-group-item-warning
%span.fa.fa-exclamation-circle.fa-fw.icon-space-r
18 years or older
- if @questionnaire.agreement_accepted && @questionnaire.code_of_conduct_accepted && @questionnaire.data_sharing_accepted
%li.list-group-item
.text-success
%span.fa.fa-check.fa-fw.icon-space-r
Event agreement, MLH Code of Conduct, and MLH Data Sharing
- else
%li.list-group-item.list-group-item-danger
%span.fa.fa-close.fa-fw.icon-space-r
One or more of the following was not accepted: Event agreement, MLH Code of Conduct, and/or MLH Data Sharing
- if @agreements.any?
- if @questionnaire.all_agreements_accepted?
%li.list-group-item
.text-success
%span.fa.fa-check.fa-fw.icon-space-r
= @questionnaire.agreements.map(&:name).join(', ')
accepted.
- else
%li.list-group-item.list-group-item-danger
%span.fa.fa-close.fa-fw.icon-space-r
Unaccepted Agreements:
= @questionnaire.unaccepted_agreements.map(&:name).join(', ')
Loading