mr_common 1.3.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +30 -9
- data/app/controllers/mr_common/dashboard_controller.rb +1 -0
- data/app/controllers/mr_common/pre_registrations/import_controller.rb +26 -0
- data/app/controllers/mr_common/pre_registrations/pre_registrations_controller.rb +48 -0
- data/app/controllers/mr_common/registrations/confirmations_controller.rb +54 -0
- data/app/controllers/mr_common/registrations/export_controller.rb +35 -4
- data/app/controllers/mr_common/registrations/public_controller.rb +24 -1
- data/app/controllers/mr_common/registrations/registrations_controller.rb +2 -0
- data/app/controllers/mr_common/registrations/resend_notifications_controller.rb +27 -0
- data/app/controllers/mr_common/registrations/success_controller.rb +1 -0
- data/app/mailers/mr_common/registration_mailer.rb +13 -3
- data/app/models/concerns/mr_common/csv_exportable.rb +6 -2
- data/app/models/mr_common/country.rb +9 -0
- data/app/models/mr_common/csv_renderer.rb +38 -0
- data/app/models/mr_common/pattern.rb +10 -0
- data/app/models/mr_common/pre_registration.rb +52 -0
- data/app/models/mr_common/pre_registration_importer.rb +91 -0
- data/app/models/mr_common/registration.rb +11 -2
- data/app/models/mr_common/registration_decorator.rb +20 -0
- data/app/models/mr_common/reminder.rb +6 -0
- data/app/models/mr_common/timezone.rb +5 -0
- data/app/views/layouts/mr_common/_navigation.html.erb +7 -0
- data/app/views/mr_common/pre_registrations/import/new.html.erb +27 -0
- data/app/views/mr_common/pre_registrations/pre_registrations/_form.html.erb +29 -0
- data/app/views/mr_common/pre_registrations/pre_registrations/index.html.erb +32 -0
- data/{lib/generators/mr_common/views/templates/mr_common/registrations/public → app/views/mr_common/pre_registrations/pre_registrations}/new.html.erb +2 -1
- data/{lib/generators/mr_common/views/templates/mr_common/registration_mailer/confirmation.html.erb → app/views/mr_common/registration_mailer/confirmed_registration.html.erb} +3 -0
- data/app/views/mr_common/registration_mailer/{confirmation.text.erb → confirmed_registration.text.erb} +2 -0
- data/app/views/mr_common/registration_mailer/revoked_registration.html.erb +5 -0
- data/app/views/mr_common/registration_mailer/revoked_registration.text.erb +6 -0
- data/app/views/mr_common/registration_mailer/unconfirmed_registration.html.erb +3 -0
- data/app/views/mr_common/registration_mailer/unconfirmed_registration.text.erb +4 -0
- data/app/views/mr_common/registrations/registrations/_form.html.erb +6 -0
- data/app/views/mr_common/registrations/registrations/index.html.erb +4 -0
- data/app/views/mr_common/registrations/registrations/show.html.erb +34 -3
- data/config/routes.rb +13 -1
- data/db/migrate/20190522151523_create_pre_registrations.rb +12 -0
- data/db/migrate/20190530220614_add_confirmed_to_registrations.rb +5 -0
- data/lib/generators/mr_common/controllers/USAGE +9 -0
- data/lib/generators/mr_common/controllers/controllers_generator.rb +24 -0
- data/lib/generators/mr_common/mailers/USAGE +16 -0
- data/lib/generators/mr_common/mailers/mailers_generator.rb +31 -0
- data/lib/generators/mr_common/models/USAGE +8 -0
- data/lib/generators/mr_common/models/models_generator.rb +23 -0
- data/lib/generators/mr_common/views/USAGE +1 -4
- data/lib/generators/mr_common/views/views_generator.rb +7 -8
- data/lib/mr_common.rb +14 -2
- data/lib/mr_common/version.rb +1 -1
- data/spec/dummy/config/initializers/mr_common.rb +10 -0
- data/spec/dummy/db/schema.rb +14 -4
- data/spec/dummy/log/development.log +1969 -50958
- data/spec/dummy/log/test.log +647 -14437
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-G/-gyHBJNssgJVEwk7sD1F9nK_dT1D1R5NjlAvcESJxME.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3d/3DI5adLgOKj6Q76fFxrLy_hKYkrlht0MEWksNkYgoXk.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3n/3NK03OBfUwDPKVYV6_11AOo3IGNUQPed4dqB-Ddv6-Q.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7d/7DbSMErmkAd0cL6q_WyLMfx7gLYQB0h9smKZ0xGjOjY.cache +2 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/9m/9MK1AG2zx0HVFVRULpQQnQQY0HiNroKnYEz2FUBzw6k.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/CO/cojbSP1f9tYoCyycggqXgW3OYb3atOkOpf-h-Axn36o.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/H6/h6GO-mL-rzWHmoiFw-uuwdny5zj_zSb1Xzun5jkza5k.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/LG/LG2fyButWQgZoNvH4qD2dBMQhl35dSysUbxsvw_2PA0.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/LZ/lZ_yNthdvXeWexZW9TZuMWs6lZBLMEF5rp7aA5Bl9uU.cache +2 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Lh/LhBzrZLgp6fzHcgWFt_B-TqHzHaPyKv9Uk67brUycZE.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/N-/N-7bXt4Ck0q2VWzHHuRPKL0a0CH_1W_eyAU59tZraxE.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Pi/PI3-Xhs-TBYEqgGeCf3hWGn6vj1qCdqBqgYRY2jNr4Q.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QQ/qqtvJX4CrLCTv4jjIg0LwoNxJUyDpLus0RIbg6D6muk.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Se/setx2SgK-JX4zwjgbekiVnvWJnbp0-2XnO0TQJfCOHU.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ue/UecY7KKAHkP6oiqpx1zkXAL9WWGqWdhgqhixQyJ82is.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/VF/VfH7y0fTeHy8aLBK_bu5OKprS0c1-GCHUzrMzp-O0_I.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/WC/WCV-7lpbJsFHZueodYuN5542p56UPNtby1LVPUjvuJU.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/WV/wvfl97Gci1mpw00EFHWc0Q9x0DLBar03PTd9BrZ7MF0.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/eP/ePjuIgA1bwfnJWATz7q6EjGfNnpvYEaKW_2aozCJFBQ.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ge/GegLYwRNBYKvfYR1-WWnx3ssHerCO6M94VPxwUTYHtM.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/h9/H95rpLdUakuAt6lpkUhlZvxsYlSb-VrfpiznZYmWnGo.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/p_/P_kWJKPROj6qDVkyzNQgx8wZmba8YaTqtWMQyGHFtuY.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/w3/w34qFl6hbbodwCEAr9Px_jzso7svjewL5BaOf6QMIN4.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wi/wi_OyVKzMxj9CcM3e2Bhab5PQSg4wh0nD-7QJQ3SVPw.cache +1 -0
- data/spec/dummy/tmp/pids/server.pid +1 -1
- data/spec/factories/registrations.rb +5 -5
- data/spec/models/registration_spec.rb +40 -0
- metadata +80 -11
- data/app/helpers/mr_common/form_helper.rb +0 -11
- data/app/models/mr_common/csv_exporter.rb +0 -35
- data/app/models/mr_common/default_csv_export_adapter.rb +0 -23
- data/app/views/mr_common/registration_mailer/confirmation.html.erb +0 -4
- data/lib/generators/mr_common/views/templates/mr_common/registration_mailer/confirmation.text.erb +0 -6
- data/lib/generators/mr_common/views/templates/mr_common/registrations/success/index.html.erb +0 -2
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "csv"
|
4
|
+
|
5
|
+
module MrCommon
|
6
|
+
# Renders collections of objects to a CSV string.
|
7
|
+
#
|
8
|
+
# @param collection [Enumerable<Object>] a collection of objects.
|
9
|
+
# @param fields [Array<String, Symbol>] fields to use as columns in the CSV.
|
10
|
+
# It is expected that each item responds to each field if sent as a message.
|
11
|
+
# @param decorator [SimpleDelegator, nil] optional wrapper class used to
|
12
|
+
# generate values for CSV rows when items in the collection don't respond to
|
13
|
+
# every field provided.
|
14
|
+
class CSVRenderer
|
15
|
+
attr_reader :collection, :decorator, :fields
|
16
|
+
|
17
|
+
def initialize(collection: [], fields: [], decorator: nil)
|
18
|
+
@collection = collection
|
19
|
+
@decorator = decorator
|
20
|
+
@fields = fields.map(&:to_sym)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Renders the provided collection to a CSV string.
|
24
|
+
#
|
25
|
+
# @return [String] the CSV file contents
|
26
|
+
def render
|
27
|
+
CSV.generate do |csv|
|
28
|
+
csv << fields
|
29
|
+
|
30
|
+
collection.each do |item|
|
31
|
+
item = decorator ? decorator.new(item) : item
|
32
|
+
row = fields.map { |field_name| item.try(field_name) }
|
33
|
+
csv << row
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,11 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module MrCommon
|
4
|
+
# Common regex patterns
|
4
5
|
class Pattern
|
5
6
|
class << self
|
7
|
+
# Matches valid email addresses. Ensures that the @ symbol is
|
8
|
+
# preceded by something resembling a username and followed by something
|
9
|
+
# resembling a domain name.
|
6
10
|
def email
|
7
11
|
/\A\S+@\S+\.\S+\z/
|
8
12
|
end
|
13
|
+
|
14
|
+
# Matches most phone numbers a person could enter. Tests for at least 7 of
|
15
|
+
# the characters that can appear in a phone number.
|
16
|
+
def phone_number
|
17
|
+
/[\d()\\x+\- ]{7,}/
|
18
|
+
end
|
9
19
|
end
|
10
20
|
end
|
11
21
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MrCommon
|
4
|
+
# When MrCommon.enable_pre_registration is true newly created Registrations
|
5
|
+
# will be checked against existing PreRegistrations. If a PreRegistration is
|
6
|
+
# found the Registration will be confirmed automatically.
|
7
|
+
#
|
8
|
+
# A PreRegistration requires a first+last name OR an email to be valid.
|
9
|
+
class PreRegistration < ApplicationRecord
|
10
|
+
validates :email, presence: true, format: MrCommon::Pattern.email, if: :should_validate_email?
|
11
|
+
validates :first_name, presence: true, if: :should_validate_name?
|
12
|
+
validates :last_name, presence: true, if: :should_validate_name?
|
13
|
+
validates :normalized_name, presence: true, if: :should_validate_name?
|
14
|
+
|
15
|
+
before_validation :normalize_email
|
16
|
+
before_validation :set_normalized_name
|
17
|
+
|
18
|
+
def self.exists_for?(registration)
|
19
|
+
email = registration.email&.downcase
|
20
|
+
name = normalized_name_from(registration).presence
|
21
|
+
|
22
|
+
exists_for_email = email.present? ? exists?(email: email) : false
|
23
|
+
exists_for_name = name.present? ? exists?(normalized_name: name) : false
|
24
|
+
exists_for_email || exists_for_name
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def self.normalized_name_from(registration_or_self)
|
30
|
+
first = registration_or_self.first_name.downcase.gsub(/\W+/, "-")
|
31
|
+
last = registration_or_self.last_name.downcase.gsub(/\W+/, "-")
|
32
|
+
spacer = first.present? && last.present? ? "-" : ""
|
33
|
+
"#{first}#{spacer}#{last}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def should_validate_email?
|
37
|
+
first_name.blank? && last_name.blank?
|
38
|
+
end
|
39
|
+
|
40
|
+
def should_validate_name?
|
41
|
+
email.blank?
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_normalized_name
|
45
|
+
self.normalized_name = PreRegistration.normalized_name_from(self)
|
46
|
+
end
|
47
|
+
|
48
|
+
def normalize_email
|
49
|
+
self.email = email.downcase
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MrCommon
|
4
|
+
# Imports PreRegistration records from a CSV file that looks like:
|
5
|
+
#
|
6
|
+
# first_name, last_name, email
|
7
|
+
# John, Smith, jsmith@example.com
|
8
|
+
# Jane, Doe, jdoe@example.com
|
9
|
+
# ,,unknown@example.com
|
10
|
+
# Name,Only,
|
11
|
+
#
|
12
|
+
# @author Corey Smedstad <csmedstad@mreach.com>
|
13
|
+
class PreRegistrationImporter
|
14
|
+
RowStruct = Struct.new(:first_name, :last_name, :email) do
|
15
|
+
# Returns true if the row does not represent a duplicate PreRegistration
|
16
|
+
# @return [Boolean]
|
17
|
+
def new?
|
18
|
+
!PreRegistration.exists_for?(self)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
ResultStruct = Struct.new(:created, :skipped)
|
23
|
+
|
24
|
+
attr_reader :csv, :current_row, :result
|
25
|
+
|
26
|
+
# @param csv [String] a the contents of a CSV file
|
27
|
+
def initialize(csv)
|
28
|
+
@csv = csv
|
29
|
+
@created = 0
|
30
|
+
@skipped = 0
|
31
|
+
end
|
32
|
+
|
33
|
+
# Attempts to create PreRegistration records for each row in the CSV
|
34
|
+
# recording the number of created and skipped records in the process.
|
35
|
+
#
|
36
|
+
# The result is memoized to prevent double imports.
|
37
|
+
#
|
38
|
+
# @returns [ResultStruct] the result of the import
|
39
|
+
def import
|
40
|
+
@result ||= perform_import
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def perform_import
|
46
|
+
PreRegistration.transaction do
|
47
|
+
rows.each do |data|
|
48
|
+
load_row(data)
|
49
|
+
|
50
|
+
if current_row.new?
|
51
|
+
make_pre_registration
|
52
|
+
else
|
53
|
+
skip_pre_registration
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
ResultStruct.new(@created, @skipped)
|
59
|
+
end
|
60
|
+
|
61
|
+
def rows
|
62
|
+
CSV.parse(csv, headers: true)
|
63
|
+
end
|
64
|
+
|
65
|
+
def load_row(data)
|
66
|
+
first_name = data[0] || ""
|
67
|
+
last_name = data[1] || ""
|
68
|
+
email = data[2] || ""
|
69
|
+
|
70
|
+
@current_row = RowStruct.new(first_name, last_name, email)
|
71
|
+
end
|
72
|
+
|
73
|
+
def make_pre_registration
|
74
|
+
pre_registration = PreRegistration.new(
|
75
|
+
first_name: current_row.first_name,
|
76
|
+
last_name: current_row.last_name,
|
77
|
+
email: current_row.email
|
78
|
+
)
|
79
|
+
|
80
|
+
if pre_registration.save
|
81
|
+
@created += 1
|
82
|
+
else
|
83
|
+
skip_pre_registration
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def skip_pre_registration
|
88
|
+
@skipped += 1
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -8,11 +8,20 @@ module MrCommon
|
|
8
8
|
|
9
9
|
validates :first_name, presence: true
|
10
10
|
validates :last_name, presence: true
|
11
|
-
validates :email, presence: true
|
11
|
+
validates :email, presence: true, format: Pattern.email
|
12
12
|
validates :company_name, presence: true
|
13
|
-
validates :telephone, presence: true
|
13
|
+
validates :telephone, presence: true, format: Pattern.phone_number
|
14
14
|
validates :job_title, presence: true
|
15
15
|
validates :contact_via_email, inclusion: [true, false]
|
16
16
|
validates :contact_via_phone, inclusion: [true, false]
|
17
|
+
|
18
|
+
validate :telephone_length
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def telephone_length
|
23
|
+
digits = telephone.gsub(/\D+/, "")
|
24
|
+
errors.add(:telephone, "must be longer") if digits.length < 7
|
25
|
+
end
|
17
26
|
end
|
18
27
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MrCommon
|
4
|
+
# Implements custom field values when exporting Registration records as CSV.
|
5
|
+
class RegistrationDecorator < SimpleDelegator
|
6
|
+
def preregistered?
|
7
|
+
__getobj__.preregistered? ? "YES" : "NO"
|
8
|
+
end
|
9
|
+
|
10
|
+
def confirmed?
|
11
|
+
__getobj__.confirmed? ? "YES" : "NO"
|
12
|
+
end
|
13
|
+
|
14
|
+
if MrCommon.registration_confirmation_strategy == :pre_register
|
15
|
+
def pre_registered?
|
16
|
+
PreRegistration.exists_for?(__getobj__) ? "YES" : "NO"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -3,6 +3,10 @@
|
|
3
3
|
require_dependency "mr_common/application_record"
|
4
4
|
|
5
5
|
module MrCommon
|
6
|
+
# Stores information for generating downloadable calendar reminders that
|
7
|
+
# appear in some emails.
|
8
|
+
#
|
9
|
+
# When
|
6
10
|
class Reminder < ApplicationRecord
|
7
11
|
validates :start_time, presence: true
|
8
12
|
validates :end_time, presence: true
|
@@ -15,6 +19,8 @@ module MrCommon
|
|
15
19
|
|
16
20
|
before_validation :parameterize_slug
|
17
21
|
|
22
|
+
scope :for_confirmed_notice, -> { where(include_in_confirmation_mailer: true) }
|
23
|
+
|
18
24
|
def to_ical
|
19
25
|
cal = Icalendar::Calendar.new
|
20
26
|
|
@@ -1,12 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module MrCommon
|
4
|
+
# Helper class for building time zone select options. Pares down the list by
|
5
|
+
# grouping locations that share ones or offsets.
|
4
6
|
class Timezone
|
5
7
|
class << self
|
8
|
+
# @return [Array<String>] list of time zone names ordered by offset
|
6
9
|
def time_zone_options
|
7
10
|
filtered_time_zones.collect(&:name)
|
8
11
|
end
|
9
12
|
|
13
|
+
# @return [Array<Array<String, String>>] list of label value pairs for
|
14
|
+
# building time zone select options ordered by offset.
|
10
15
|
def time_zone_select_options
|
11
16
|
filtered_time_zones.collect do |tz|
|
12
17
|
["(UTC#{tz_utc_offset(tz)}) #{tz_friendly_name(tz)}", tz.name]
|
@@ -13,6 +13,13 @@
|
|
13
13
|
<li>
|
14
14
|
<%= link_to 'Reminders', reminders_path %>
|
15
15
|
</li>
|
16
|
+
|
17
|
+
<% if MrCommon.registration_confirmation_strategy == :pre_register %>
|
18
|
+
<li>
|
19
|
+
<%= link_to 'PreRegistrations', pre_registrations_path %>
|
20
|
+
</li>
|
21
|
+
<% end %>
|
22
|
+
|
16
23
|
<% if MrCommon.authentication_method_name.present? %>
|
17
24
|
<li>
|
18
25
|
<%= link_to 'Log Out', main_app.send(MrCommon.logout_path_helper), method: MrCommon.logout_path_method %>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="col">
|
3
|
+
<h1>Import Pre Registrations</h1>
|
4
|
+
<%= form_with scope: :import, url: pre_registrations_import_index_url, local: true do |f| %>
|
5
|
+
<fieldset>
|
6
|
+
<legend>Import</legend>
|
7
|
+
<div class="form-group">
|
8
|
+
<%= f.label :csv_file, "CSV File" %>
|
9
|
+
<%= f.file_field :csv_file, required: true, accept: "text/csv" %>
|
10
|
+
</div>
|
11
|
+
<p>The CSV file should be formatted like this example:</p>
|
12
|
+
<pre>
|
13
|
+
first_name, last_name, email
|
14
|
+
John, Smith, jsmith@example.com
|
15
|
+
Jane, Doe, jdoe@example.com
|
16
|
+
,,unknown@example.com
|
17
|
+
Name,Only,
|
18
|
+
</pre>
|
19
|
+
<p>If you have a spreadsheet with these columns, "Save as..." and choose the CSV as the file type.</p>
|
20
|
+
<p>It is assumed that your CSV has column headings. The first non-empty row will be ignored.</p>
|
21
|
+
</fieldset>
|
22
|
+
|
23
|
+
<%= f.submit "Import" %>
|
24
|
+
<%= link_to "Cancel", pre_registrations_path, class: 'button-secondary' %>
|
25
|
+
<% end %>
|
26
|
+
</div>
|
27
|
+
</div>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<%= form_with model: @pre_registration, local: true do |f| %>
|
2
|
+
<fieldset>
|
3
|
+
<legend>Pre-registration details</legend>
|
4
|
+
<%= f.form_group :email do %>
|
5
|
+
<%= f.label :email %>
|
6
|
+
<%= f.text_field :email %>
|
7
|
+
<%= f.errors :email %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<%= f.form_group :first_name do %>
|
11
|
+
<%= f.label :first_name %>
|
12
|
+
<%= f.text_field :first_name %>
|
13
|
+
<%= f.errors :first_name %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<%= f.form_group :last_name do %>
|
17
|
+
<%= f.label :last_name %>
|
18
|
+
<%= f.text_field :last_name %>
|
19
|
+
<%= f.errors :last_name %>
|
20
|
+
<% end %>
|
21
|
+
</fieldset>
|
22
|
+
|
23
|
+
<%= f.submit "Save" %>
|
24
|
+
<% if @pre_registration.new_record? %>
|
25
|
+
<%= link_to "Cancel", pre_registrations_path, class: 'button-secondary' %>
|
26
|
+
<% else %>
|
27
|
+
<%= link_to "Cancel", pre_registration_path(@pre_registration), class: 'button-secondary' %>
|
28
|
+
<% end %>
|
29
|
+
<% end %>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="col">
|
3
|
+
<h1>PreRegistrations</h1>
|
4
|
+
<p>
|
5
|
+
<%= link_to 'New', new_pre_registration_path, class: 'button' %>
|
6
|
+
</p>
|
7
|
+
</div>
|
8
|
+
</div>
|
9
|
+
<div class="row">
|
10
|
+
<div class="col">
|
11
|
+
<table>
|
12
|
+
<thead>
|
13
|
+
<tr>
|
14
|
+
<th>Email</th>
|
15
|
+
<th>First</th>
|
16
|
+
<th>Last</th>
|
17
|
+
<th>Actions</th>
|
18
|
+
</tr>
|
19
|
+
</thead>
|
20
|
+
<tbody>
|
21
|
+
<% @pre_registration.each do |r| %>
|
22
|
+
<tr>
|
23
|
+
<td><%= r.email %></td>
|
24
|
+
<td><%= r.first_name %></td>
|
25
|
+
<td><%= r.last_name %></td>
|
26
|
+
<td><%= link_to 'Delete', r, method: :delete, data: { confirm: 'Are you sure?' } %></td>
|
27
|
+
</tr>
|
28
|
+
<% end %>
|
29
|
+
</tbody>
|
30
|
+
</table>
|
31
|
+
</div>
|
32
|
+
</div>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<h1>Your registration is no longer confirmed</h1>
|
2
|
+
|
3
|
+
<p>Thank you for your interest in our invitation-only event.</p>
|
4
|
+
|
5
|
+
<p>Unfortunately, we aren’t able to accommodate your registration at this time. If we are able to confirm a spot for you, we will notify you before the event.</p>
|