effective_classifieds 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +122 -0
- data/Rakefile +18 -0
- data/app/assets/config/effective_classifieds_manifest.js +3 -0
- data/app/assets/javascripts/effective_classifieds/base.js +0 -0
- data/app/assets/javascripts/effective_classifieds.js +1 -0
- data/app/assets/stylesheets/effective_classifieds/base.scss +0 -0
- data/app/assets/stylesheets/effective_classifieds.scss +1 -0
- data/app/controllers/admin/classified_submissions_controller.rb +19 -0
- data/app/controllers/admin/classifieds_controller.rb +20 -0
- data/app/controllers/effective/classified_submissions_controller.rb +31 -0
- data/app/controllers/effective/classifieds_controller.rb +53 -0
- data/app/datatables/admin/effective_classified_submissions_datatable.rb +22 -0
- data/app/datatables/admin/effective_classifieds_datatable.rb +61 -0
- data/app/datatables/effective_classified_submissions_datatable.rb +37 -0
- data/app/datatables/effective_classifieds_datatable.rb +25 -0
- data/app/helpers/effective_classifieds_helper.rb +7 -0
- data/app/mailers/effective/classifieds_mailer.rb +22 -0
- data/app/models/concerns/effective_classifieds_classified_submission.rb +112 -0
- data/app/models/effective/classified.rb +164 -0
- data/app/models/effective/classified_submission.rb +7 -0
- data/app/views/admin/classifieds/_form.html.haml +12 -0
- data/app/views/admin/classifieds/_form_access.html.haml +10 -0
- data/app/views/admin/classifieds/_form_classified.html.haml +3 -0
- data/app/views/effective/classified_submissions/_classified.haml +12 -0
- data/app/views/effective/classified_submissions/_classified_submission.html.haml +8 -0
- data/app/views/effective/classified_submissions/_content.html.haml +1 -0
- data/app/views/effective/classified_submissions/_dashboard.html.haml +28 -0
- data/app/views/effective/classified_submissions/_layout.html.haml +3 -0
- data/app/views/effective/classified_submissions/_summary.html.haml +30 -0
- data/app/views/effective/classified_submissions/classified.html.haml +17 -0
- data/app/views/effective/classified_submissions/start.html.haml +16 -0
- data/app/views/effective/classified_submissions/submitted.html.haml +13 -0
- data/app/views/effective/classified_submissions/summary.html.haml +8 -0
- data/app/views/effective/classifieds/_classified.html.haml +50 -0
- data/app/views/effective/classifieds/_dashboard.html.haml +8 -0
- data/app/views/effective/classifieds/_fields.html.haml +28 -0
- data/app/views/effective/classifieds/_form.html.haml +3 -0
- data/app/views/effective/classifieds/_layout.html.haml +1 -0
- data/app/views/effective/classifieds/_spacer.html.haml +1 -0
- data/app/views/effective/classifieds/index.html.haml +8 -0
- data/app/views/effective/classifieds/show.html.haml +8 -0
- data/app/views/effective/classifieds_mailer/classified_submitted.html.haml +16 -0
- data/app/views/layouts/effective_classifieds_mailer_layout.html.haml +7 -0
- data/config/effective_classifieds.rb +45 -0
- data/config/routes.rb +24 -0
- data/db/migrate/01_create_effective_classifieds.rb.erb +62 -0
- data/db/seeds.rb +1 -0
- data/lib/effective_classifieds/engine.rb +18 -0
- data/lib/effective_classifieds/version.rb +3 -0
- data/lib/effective_classifieds.rb +45 -0
- data/lib/generators/effective_classifieds/install_generator.rb +31 -0
- data/lib/generators/templates/effective_classifieds_mailer_preview.rb +4 -0
- data/lib/tasks/effective_classifieds_tasks.rake +8 -0
- metadata +251 -0
@@ -0,0 +1,164 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Effective
|
4
|
+
class Classified < ActiveRecord::Base
|
5
|
+
self.table_name = EffectiveClassifieds.classifieds_table_name.to_s
|
6
|
+
|
7
|
+
attr_accessor :current_user
|
8
|
+
|
9
|
+
acts_as_slugged
|
10
|
+
log_changes if respond_to?(:log_changes)
|
11
|
+
acts_as_role_restricted if respond_to?(:acts_as_role_restricted)
|
12
|
+
|
13
|
+
# This will be the owner of the classified submission
|
14
|
+
# Or the admin user that created it
|
15
|
+
belongs_to :owner, polymorphic: true
|
16
|
+
|
17
|
+
# When submitted through the wizard
|
18
|
+
belongs_to :classified_submission, polymorphic: true, optional: true
|
19
|
+
|
20
|
+
has_rich_text :body
|
21
|
+
|
22
|
+
acts_as_statused(
|
23
|
+
:draft, # Initial state
|
24
|
+
:submitted, # Once submitted by the classified submission.
|
25
|
+
:approved # Exit state. Classified was approved.
|
26
|
+
)
|
27
|
+
|
28
|
+
effective_resource do
|
29
|
+
title :string
|
30
|
+
category :string
|
31
|
+
|
32
|
+
organization :string # Or seller
|
33
|
+
location :string
|
34
|
+
|
35
|
+
website :string
|
36
|
+
email :string
|
37
|
+
phone :string
|
38
|
+
|
39
|
+
# Logic
|
40
|
+
start_on :date
|
41
|
+
end_on :date
|
42
|
+
|
43
|
+
# Acts as Slugged
|
44
|
+
slug :string
|
45
|
+
|
46
|
+
# Acts as Statused
|
47
|
+
status :string, permitted: false
|
48
|
+
status_steps :text, permitted: false
|
49
|
+
|
50
|
+
# Access
|
51
|
+
roles_mask :integer
|
52
|
+
authenticate_user :boolean
|
53
|
+
|
54
|
+
archived :boolean
|
55
|
+
|
56
|
+
timestamps
|
57
|
+
end
|
58
|
+
|
59
|
+
scope :sorted, -> { order(:id) }
|
60
|
+
scope :deep, -> { with_rich_text_body }
|
61
|
+
|
62
|
+
scope :upcoming, -> { where(arel_table[:end_on].gt(Time.zone.now)) }
|
63
|
+
scope :past, -> { where(arel_table[:end_on].lteq(Time.zone.now)) }
|
64
|
+
|
65
|
+
scope :unarchived, -> { where(archived: false) }
|
66
|
+
scope :archived, -> { where(archived: true) }
|
67
|
+
|
68
|
+
scope :published, -> {
|
69
|
+
approved
|
70
|
+
.unarchived
|
71
|
+
.where(arel_table[:start_on].lteq(Time.zone.now))
|
72
|
+
.where(arel_table[:end_on].gt(Time.zone.now))
|
73
|
+
}
|
74
|
+
|
75
|
+
scope :paginate, -> (page: nil, per_page: nil) {
|
76
|
+
page = (page || 1).to_i
|
77
|
+
offset = [(page - 1), 0].max * (per_page || EffectiveClassifieds.per_page)
|
78
|
+
|
79
|
+
limit(per_page).offset(offset)
|
80
|
+
}
|
81
|
+
|
82
|
+
scope :classifieds, -> (user: nil, unpublished: false) {
|
83
|
+
scope = all.deep.sorted
|
84
|
+
|
85
|
+
if defined?(EffectiveRoles) && EffectiveClassifieds.use_effective_roles
|
86
|
+
scope = scope.for_role(user&.roles)
|
87
|
+
end
|
88
|
+
|
89
|
+
if user.blank?
|
90
|
+
scope = scope.where(authenticate_user: false)
|
91
|
+
end
|
92
|
+
|
93
|
+
unless unpublished
|
94
|
+
scope = scope.published
|
95
|
+
end
|
96
|
+
|
97
|
+
scope
|
98
|
+
}
|
99
|
+
|
100
|
+
before_validation(if: -> { current_user.present? }) do
|
101
|
+
self.owner ||= current_user
|
102
|
+
end
|
103
|
+
|
104
|
+
# Automatically approve submissions created by admins outside the submissions wizard
|
105
|
+
before_validation(if: -> { new_record? && classified_submission.blank? }) do
|
106
|
+
assign_attributes(status: :approved)
|
107
|
+
end
|
108
|
+
|
109
|
+
validates :title, presence: true, length: { maximum: 200 }
|
110
|
+
validates :category, presence: true
|
111
|
+
validates :body, presence: true
|
112
|
+
|
113
|
+
validates :start_on, presence: true
|
114
|
+
validates :end_on, presence: true
|
115
|
+
validates :location, presence: true
|
116
|
+
|
117
|
+
validates :organization, presence: true
|
118
|
+
validates :email, presence: true
|
119
|
+
validates :phone, presence: true
|
120
|
+
|
121
|
+
validate(if: -> { start_on.present? && end_on.present? }) do
|
122
|
+
self.errors.add(:end_on, 'must be after start date') if end_on < start_on
|
123
|
+
end
|
124
|
+
|
125
|
+
validate(if: -> { start_on.present? && end_on.present? && EffectiveClassifieds.max_duration.present? }) do
|
126
|
+
if (end_on - start_on) > EffectiveClassifieds.max_duration
|
127
|
+
distance = ApplicationController.helpers.distance_of_time_in_words(end_on + EffectiveClassifieds.max_duration, end_on).gsub('about', '').strip
|
128
|
+
self.errors.add(:end_on, "must be within #{distance} of start date")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
validate(if: -> { category.present? }) do
|
133
|
+
self.errors.add(:category, 'is invalid') unless Array(EffectiveClassifieds.categories).include?(category)
|
134
|
+
end
|
135
|
+
|
136
|
+
def to_s
|
137
|
+
title.presence || 'New Classified'
|
138
|
+
end
|
139
|
+
|
140
|
+
def published?
|
141
|
+
return false unless approved?
|
142
|
+
return false if archived?
|
143
|
+
return false if start_on.blank? || (Time.zone.now < start_on)
|
144
|
+
return false if end_on.present? && (Time.zone.now >= end_on)
|
145
|
+
true
|
146
|
+
end
|
147
|
+
|
148
|
+
def submit!
|
149
|
+
submitted!
|
150
|
+
approve! if EffectiveClassifieds.auto_approve
|
151
|
+
|
152
|
+
after_commit do
|
153
|
+
EffectiveClassifieds.send_email(:classified_submitted, self)
|
154
|
+
end
|
155
|
+
|
156
|
+
true
|
157
|
+
end
|
158
|
+
|
159
|
+
def approve!
|
160
|
+
approved!
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
= tabs do
|
2
|
+
= tab 'Classified' do
|
3
|
+
= render 'admin/classifieds/form_classified', classified: classified
|
4
|
+
|
5
|
+
- if classified.persisted?
|
6
|
+
|
7
|
+
= tab 'Access' do
|
8
|
+
= render '/admin/classifieds/form_access', classified: classified
|
9
|
+
|
10
|
+
- if classified.respond_to?(:log_changes_datatable)
|
11
|
+
= tab 'Logs' do
|
12
|
+
= render_inline_datatable(classified.log_changes_datatable)
|
@@ -0,0 +1,10 @@
|
|
1
|
+
= effective_form_with(model: classified, url: classified.persisted? ? effective_classifieds.admin_classified_path(classified.id) : effective_classifieds.admin_classifieds_path) do |f|
|
2
|
+
= f.check_box :authenticate_user, label: 'Yes, the user must be be signed in to view this classified', hint: 'Sign up is required to register for any classified'
|
3
|
+
|
4
|
+
- if EffectiveClassifieds.use_effective_roles
|
5
|
+
= f.checks :roles, EffectiveRoles.roles_collection(f.object)
|
6
|
+
|
7
|
+
%p.text-hint
|
8
|
+
* leave blank for a regular public classified that anyone can view
|
9
|
+
|
10
|
+
= f.submit
|
@@ -0,0 +1,12 @@
|
|
1
|
+
= card do
|
2
|
+
.row
|
3
|
+
.col-sm
|
4
|
+
%h5.card-title= classified_submission.wizard_step_title(:classified)
|
5
|
+
.col-sm-auto.text-right
|
6
|
+
= link_to('Edit', wizard_path(:classified)) if edit_effective_classified_submissions_wizard?
|
7
|
+
|
8
|
+
- classified = classified_submission.classified
|
9
|
+
|
10
|
+
- if classified.present?
|
11
|
+
= render('effective/classifieds/classified', classified: classified) do
|
12
|
+
= classified.body
|
@@ -0,0 +1,8 @@
|
|
1
|
+
.effective-classified-submission
|
2
|
+
- blacklist = EffectiveClassifieds.ClassifiedSubmission.required_wizard_steps
|
3
|
+
- steps = classified_submission.required_steps - blacklist
|
4
|
+
|
5
|
+
= render "effective/classified_submissions/summary", classified_submission: classified_submission
|
6
|
+
|
7
|
+
- steps.select { |step| classified_submission.has_completed_step?(step) }.each do |partial|
|
8
|
+
= render "effective/classified_submissions/#{partial}", classified_submission: classified_submission, step: partial
|
@@ -0,0 +1 @@
|
|
1
|
+
-# Intentionally blank
|
@@ -0,0 +1,28 @@
|
|
1
|
+
-# In progress submission
|
2
|
+
- submission = EffectiveClassifieds.ClassifiedSubmission.in_progress.for(current_user).first
|
3
|
+
- datatable = EffectiveResources.best('EffectiveClassifiedSubmissionsDatatable').new(self, namespace: :effective)
|
4
|
+
|
5
|
+
- if submission.present?
|
6
|
+
%h2 In Progress Classified Submissions
|
7
|
+
|
8
|
+
%p
|
9
|
+
Your submission for #{submission.classified.presence || 'a classified'} is incomplete
|
10
|
+
|
11
|
+
%p
|
12
|
+
Please
|
13
|
+
= link_to("Continue submission for #{submission.classified.presence || 'a classified'}", effective_classifieds.classified_submission_build_path(submission, submission.next_step), 'data-turbolinks' => false, class: 'btn btn-primary')
|
14
|
+
or you can
|
15
|
+
= link_to('Abandon submission', effective_classifieds.classified_submission_path(submission), 'data-confirm': "Really delete #{submission}?", 'data-method': :delete, class: 'btn btn-danger')
|
16
|
+
to submit another.
|
17
|
+
|
18
|
+
%hr
|
19
|
+
|
20
|
+
%h2 Classified Submissions
|
21
|
+
|
22
|
+
- if datatable.present?
|
23
|
+
= render_simple_datatable(datatable)
|
24
|
+
- else
|
25
|
+
%p You have no past classified submissions. When you do, we'll show them here.
|
26
|
+
|
27
|
+
- if submission.blank?
|
28
|
+
%p= link_to 'Submit New Classified', effective_classifieds.new_classified_submission_path, class: 'btn btn-primary'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
= card('Classified Submission') do
|
2
|
+
- classified = classified_submission.classified
|
3
|
+
|
4
|
+
%table.table.table-sm
|
5
|
+
%tbody
|
6
|
+
%tr
|
7
|
+
%th.border-0 Classified
|
8
|
+
%td.border-0
|
9
|
+
|
10
|
+
- if classified&.published?
|
11
|
+
= link_to(classified, effective_classifieds.classified_path(classified), target: '_blank')
|
12
|
+
- else
|
13
|
+
= classified.presence || 'Classified was deleted'
|
14
|
+
|
15
|
+
- if request.path.start_with?('/admin')
|
16
|
+
%tr
|
17
|
+
%th Owner
|
18
|
+
%td
|
19
|
+
- url = (polymorphic_admin_path(classified_submission.owner) rescue "/admin/users/#{classified_submission.owner.to_param}/edit")
|
20
|
+
= link_to(classified_submission.owner, url)
|
21
|
+
- else
|
22
|
+
%tr
|
23
|
+
%th Owner
|
24
|
+
%td= classified_submission.owner
|
25
|
+
|
26
|
+
- if classified&.was_submitted?
|
27
|
+
%tr
|
28
|
+
%th Status
|
29
|
+
%td
|
30
|
+
%span.badge.badge-secondary= classified.status
|
@@ -0,0 +1,17 @@
|
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/classified_submissions/content', resource: resource
|
3
|
+
|
4
|
+
.card
|
5
|
+
.card-body
|
6
|
+
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
7
|
+
= f.hidden_field :id
|
8
|
+
|
9
|
+
= f.fields_for :classified, (f.object.classified || f.object.build_classified) do |fc|
|
10
|
+
= fc.hidden_field :id
|
11
|
+
|
12
|
+
= fc.hidden_field :owner_id, value: f.object.owner_id
|
13
|
+
= fc.hidden_field :owner_type, value: f.object.owner_type
|
14
|
+
|
15
|
+
= render('effective/classifieds/fields', f: fc, classified: fc.object)
|
16
|
+
|
17
|
+
= f.save 'Save and Continue'
|
@@ -0,0 +1,16 @@
|
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/classified_submissions/content', resource: resource
|
3
|
+
|
4
|
+
.card
|
5
|
+
.card-body
|
6
|
+
%p Welcome #{current_user}!
|
7
|
+
|
8
|
+
%p You are about to submit a classified
|
9
|
+
|
10
|
+
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
11
|
+
= f.hidden_field :id
|
12
|
+
|
13
|
+
= f.hidden_field :owner_type
|
14
|
+
= f.hidden_field :owner_id
|
15
|
+
|
16
|
+
= f.save 'Save and Continue'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/classified_submissions/content', resource: resource
|
3
|
+
|
4
|
+
- raise('expected a submitted classified_submission') unless resource.was_submitted?
|
5
|
+
|
6
|
+
.alert.alert-warning.mb-4
|
7
|
+
Successfully submitted on #{resource.submitted_at.strftime('%F')}.
|
8
|
+
|
9
|
+
= link_to "Return to Dashboard", root_path, class: 'btn btn-lg btn-primary mb-4'
|
10
|
+
|
11
|
+
= render 'effective/classified_submissions/classified_submission', classified_submission: resource
|
12
|
+
|
13
|
+
= link_to "Return to Dashboard", root_path, class: 'btn btn-lg btn-primary'
|
@@ -0,0 +1,8 @@
|
|
1
|
+
= render 'layout' do
|
2
|
+
= render 'effective/classified_submissions/content', resource: resource
|
3
|
+
|
4
|
+
= render('effective/classified_submissions/classified_submission', classified_submission: resource)
|
5
|
+
|
6
|
+
= effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
|
7
|
+
= f.hidden_field :id
|
8
|
+
= f.submit 'Submit Classified', class: 'btn btn-primary'
|
@@ -0,0 +1,50 @@
|
|
1
|
+
.card.effective-classified
|
2
|
+
.card-body
|
3
|
+
%h5.card-title= classified.title
|
4
|
+
|
5
|
+
%table.table.effective-classified-table
|
6
|
+
%tbody
|
7
|
+
%tr
|
8
|
+
%td Category
|
9
|
+
%td= classified.category
|
10
|
+
|
11
|
+
%tr
|
12
|
+
%td Available
|
13
|
+
%td #{classified.start_on&.strftime('%F')} to #{classified.end_on&.strftime('%F')}
|
14
|
+
|
15
|
+
%tr
|
16
|
+
%td Location
|
17
|
+
%td= classified.location.presence || '-'
|
18
|
+
|
19
|
+
%tr
|
20
|
+
%td Website
|
21
|
+
%td
|
22
|
+
- if classified.website.present?
|
23
|
+
= link_to(classified.website, classified.website, target: '_blank')
|
24
|
+
- else
|
25
|
+
= '-'
|
26
|
+
|
27
|
+
%tr
|
28
|
+
%td Contact
|
29
|
+
%td= classified.organization
|
30
|
+
|
31
|
+
%tr
|
32
|
+
%td Email
|
33
|
+
%td
|
34
|
+
- if classified.email.present?
|
35
|
+
= mail_to(classified.email)
|
36
|
+
- else
|
37
|
+
= '-'
|
38
|
+
|
39
|
+
%tr
|
40
|
+
%td Phone
|
41
|
+
%td
|
42
|
+
- if classified.phone.present?
|
43
|
+
= classified.phone
|
44
|
+
- else
|
45
|
+
= '-'
|
46
|
+
|
47
|
+
- if block_given?
|
48
|
+
= yield
|
49
|
+
- else
|
50
|
+
%p= link_to('View Classified', effective_classifieds.classified_path(classified), class: 'btn btn-primary')
|
@@ -0,0 +1,8 @@
|
|
1
|
+
%h2 Classifieds
|
2
|
+
|
3
|
+
- published = Effective::Classified.classifieds(user: current_user).count
|
4
|
+
|
5
|
+
- datatable = EffectiveClassifiedsDatatable.new(self, namespace: :effective)
|
6
|
+
= render_datatable(datatable, simple: true)
|
7
|
+
|
8
|
+
%p= link_to 'View All Classifieds', effective_classifieds.classifieds_path, class: 'btn btn-primary'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
= f.text_field :title
|
2
|
+
= f.select :category, EffectiveClassifieds.categories, required: true
|
3
|
+
|
4
|
+
- if f.object.persisted? || f.object.errors.include?(:slug)
|
5
|
+
- current_url = (effective_classifieds.classified_url(f.object) rescue nil)
|
6
|
+
= f.text_field :slug, hint: "The slug controls this resource's internet address. Be careful, changing the slug will break links that other websites may have to the old address.<br>#{('This is currently reachable via ' + link_to(current_url.gsub(f.object.slug, '<strong>' + f.object.slug + '</strong>').html_safe, current_url)) if current_url }".html_safe
|
7
|
+
|
8
|
+
- minDate = [Time.zone.now, f.object.created_at].compact.min
|
9
|
+
|
10
|
+
= f.date_field :start_on, label: "Classified Start",
|
11
|
+
hint: 'The classified ad will be displayed starting on this date',
|
12
|
+
input_js: { minDate: minDate.strftime('%F') }
|
13
|
+
|
14
|
+
= f.date_field :end_on, label: "Classified End",
|
15
|
+
hint: 'The classified ad will no longer be displayed on this date'
|
16
|
+
|
17
|
+
- if f.object.persisted? && !f.object.draft?
|
18
|
+
= f.check_box :archived, label: 'Yes, this classified is archived and will not be displayed'
|
19
|
+
|
20
|
+
%h2 Classified Content
|
21
|
+
= f.rich_text_area :body, hint: 'The main body of your classified'
|
22
|
+
= f.text_field :location
|
23
|
+
= f.url_field :website
|
24
|
+
|
25
|
+
%h2 Contact Information
|
26
|
+
= f.text_field :organization
|
27
|
+
= f.email_field :email
|
28
|
+
= f.tel_field :phone
|
@@ -0,0 +1 @@
|
|
1
|
+
= yield
|
@@ -0,0 +1 @@
|
|
1
|
+
%hr
|
@@ -0,0 +1,8 @@
|
|
1
|
+
= render 'layout' do
|
2
|
+
.effective-classified
|
3
|
+
- unless @classified.published?
|
4
|
+
.alert.alert-warning This classified is currently unavailable.
|
5
|
+
|
6
|
+
= render 'effective/classifieds/classified', classified: @classified do
|
7
|
+
.classified-body.classified-content
|
8
|
+
= @classified.body
|
@@ -0,0 +1,16 @@
|
|
1
|
+
%p Hello Admin!
|
2
|
+
|
3
|
+
- if @classified.published?
|
4
|
+
%p The following classified has been submitted and is published online:
|
5
|
+
- else
|
6
|
+
%p The following classified has been submitted and is awaiting your approval:
|
7
|
+
%p= link_to('Approve Classified', effective_classifieds.edit_admin_classified_path(@classified))
|
8
|
+
|
9
|
+
= render('effective/classifieds/classified', classified: @classified) do
|
10
|
+
%p= @classified.body
|
11
|
+
|
12
|
+
%hr
|
13
|
+
|
14
|
+
%p= link_to('View Classified', effective_classifieds.classified_path(@classified))
|
15
|
+
|
16
|
+
%p Have a great day!
|
@@ -0,0 +1,45 @@
|
|
1
|
+
EffectiveClassifieds.setup do |config|
|
2
|
+
config.classifieds_table_name = :classifieds
|
3
|
+
config.classified_submissions_table_name = :classified_submissions
|
4
|
+
|
5
|
+
# Every classified must have a category.
|
6
|
+
config.categories = ['Job Board', 'Equipment Sales']
|
7
|
+
|
8
|
+
# Layout Settings
|
9
|
+
# Configure the Layout per controller, or all at once
|
10
|
+
# config.layout = { application: 'application', admin: 'admin' }
|
11
|
+
|
12
|
+
# Classified Settings
|
13
|
+
# config.classified_submission_class_name = 'Effective::ClassifiedSubmission'
|
14
|
+
|
15
|
+
# Pagination length on the Classified#index page
|
16
|
+
config.per_page = 10
|
17
|
+
|
18
|
+
# Classified can be restricted by role
|
19
|
+
config.use_effective_roles = true
|
20
|
+
|
21
|
+
# Automatically end classifieds after this duration
|
22
|
+
config.max_duration = 3.months
|
23
|
+
|
24
|
+
# Automatically approve classified submissions, otherwise require admin approval
|
25
|
+
config.auto_approve = false
|
26
|
+
|
27
|
+
# Mailer Configuration
|
28
|
+
# Configure the class responsible to send e-mails.
|
29
|
+
# config.mailer = 'Effective::ClassifiedsMailer'
|
30
|
+
|
31
|
+
# Configure the parent class responsible to send e-mails.
|
32
|
+
# config.parent_mailer = 'ActionMailer::Base'
|
33
|
+
|
34
|
+
# Default deliver method
|
35
|
+
# config.deliver_method = :deliver_later
|
36
|
+
|
37
|
+
# Default layout
|
38
|
+
# config.mailer_layout = 'effective_classifieds_mailer_layout'
|
39
|
+
|
40
|
+
# Default From
|
41
|
+
config.mailer_sender = "no-reply@example.com"
|
42
|
+
|
43
|
+
# Send Admin correspondence To
|
44
|
+
config.mailer_admin = "admin@example.com"
|
45
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Rails.application.routes.draw do
|
4
|
+
mount EffectiveClassifieds::Engine => '/', as: 'effective_classifieds'
|
5
|
+
end
|
6
|
+
|
7
|
+
EffectiveClassifieds::Engine.routes.draw do
|
8
|
+
# Public routes
|
9
|
+
scope module: 'effective' do
|
10
|
+
resources :classifieds, only: [:index, :show, :edit, :update]
|
11
|
+
|
12
|
+
resources :classified_submissions, only: [:new, :show, :destroy] do
|
13
|
+
resources :build, controller: :classified_submissions, only: [:show, :update]
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
namespace :admin do
|
19
|
+
resources :classifieds, except: [:show] do
|
20
|
+
post :approve, on: :member
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
class CreateEffectiveClassifieds < ActiveRecord::Migration[6.1]
|
2
|
+
def change
|
3
|
+
create_table <%= @classifieds_table_name %> do |t|
|
4
|
+
t.integer :classified_submission_id
|
5
|
+
t.string :classified_submission_type
|
6
|
+
|
7
|
+
t.integer :owner_id
|
8
|
+
t.string :owner_type
|
9
|
+
|
10
|
+
t.string :title
|
11
|
+
t.string :category
|
12
|
+
|
13
|
+
t.string :organization
|
14
|
+
t.string :location
|
15
|
+
|
16
|
+
t.string :website
|
17
|
+
t.string :email
|
18
|
+
t.string :phone
|
19
|
+
|
20
|
+
t.datetime :start_on
|
21
|
+
t.datetime :end_on
|
22
|
+
|
23
|
+
t.string :slug
|
24
|
+
|
25
|
+
t.string :status
|
26
|
+
t.text :status_steps
|
27
|
+
|
28
|
+
t.integer :roles_mask
|
29
|
+
t.boolean :authenticate_user, default: false
|
30
|
+
|
31
|
+
t.boolean :archived, default: false
|
32
|
+
|
33
|
+
t.timestamps
|
34
|
+
end
|
35
|
+
|
36
|
+
add_index :classifieds, [:owner_id, :owner_type]
|
37
|
+
add_index :classifieds, :slug
|
38
|
+
|
39
|
+
create_table <%= @classified_submissions_table_name %> do |t|
|
40
|
+
t.string :token
|
41
|
+
|
42
|
+
t.integer :owner_id
|
43
|
+
t.string :owner_type
|
44
|
+
|
45
|
+
# Acts as Statused
|
46
|
+
t.string :status
|
47
|
+
t.text :status_steps
|
48
|
+
|
49
|
+
# Acts as Wizard
|
50
|
+
t.text :wizard_steps
|
51
|
+
|
52
|
+
# Dates
|
53
|
+
t.datetime :submitted_at
|
54
|
+
|
55
|
+
t.datetime :updated_at
|
56
|
+
t.datetime :created_at
|
57
|
+
end
|
58
|
+
|
59
|
+
add_index :classified_submissions, [:owner_id, :owner_type]
|
60
|
+
add_index :classified_submissions, :token
|
61
|
+
end
|
62
|
+
end
|
data/db/seeds.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
puts "Running effective_classifieds seeds"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module EffectiveClassifieds
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
engine_name 'effective_classifieds'
|
4
|
+
|
5
|
+
# Set up our default configuration options.
|
6
|
+
initializer 'effective_classifieds.defaults', before: :load_config_initializers do |app|
|
7
|
+
eval File.read("#{config.root}/config/effective_classifieds.rb")
|
8
|
+
end
|
9
|
+
|
10
|
+
# Include acts_as_addressable concern and allow any ActiveRecord object to call it
|
11
|
+
initializer 'effective_classifieds.active_record' do |app|
|
12
|
+
ActiveSupport.on_load :active_record do
|
13
|
+
ActiveRecord::Base.extend(EffectiveClassifiedsClassifiedSubmission::Base)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|