Skip to content

Commit

Permalink
Create Speaker module for Admin (#182)
Browse files Browse the repository at this point in the history
* Create Factory for events

* Generate Speaker module for admin
- Add HTTParty to validate links
- Add views, controllers, policies, model for speaker

* Config custom error view to adapt to bootstrap

* Fix lint errors
  • Loading branch information
luciagirasoles authored Aug 16, 2023
1 parent 3a96127 commit b96e0ca
Show file tree
Hide file tree
Showing 31 changed files with 705 additions and 127 deletions.
5 changes: 5 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ module.exports = {
},
],
},
settings: {
react: {
version: 'detect',
},
},
overrides: [
{
files: [
Expand Down
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ gem 'google_drive', git: 'https://github.com/wnbrb/google-drive-ruby.git', branc
# cuts off a string of HTML
gem 'truncate_html', '~> 0.9.3'

# quickly call web links
gem 'httpparty', '~> 0.2'

group :development, :test do
gem 'byebug', platforms: %i[mri mingw x64_mingw]
gem 'faker', '~> 2.18.0'
Expand Down
11 changes: 9 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ GEM
railties (>= 5.0.0)
faker (2.18.0)
i18n (>= 1.6, < 2)
faraday (2.7.10)
faraday (2.7.4)
faraday-net_http (>= 2.0, < 3.1)
ruby2_keywords (>= 0.0.4)
faraday-mashify (0.1.1)
Expand Down Expand Up @@ -154,8 +154,13 @@ GEM
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
hashie (5.0.0)
httparty (0.21.0)
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
i18n (1.14.1)
httpparty (0.2.0)
httparty (> 0)
i18n (1.12.0)
concurrent-ruby (~> 1.0)
io-console (0.6.0)
irb (1.7.4)
Expand Down Expand Up @@ -188,6 +193,7 @@ GEM
minitest (5.19.0)
msgpack (1.7.2)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.3.0)
net-imap (0.3.7)
date
Expand Down Expand Up @@ -396,6 +402,7 @@ DEPENDENCIES
factory_bot_rails (~> 6.2.0)
faker (~> 2.18.0)
google_drive!
httpparty (~> 0.2)
jbuilder (~> 2.7)
jsbundling-rails (~> 1.1)
jwt (>= 2.6.0)
Expand Down
95 changes: 95 additions & 0 deletions app/controllers/admin/speakers_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# frozen_string_literal: true
module Admin
class SpeakersController < AdminController
before_action :authorize_event
before_action :set_speaker, only: %w[show edit update destroy]

# GET /admin/speakers
def index
@speakers = Speaker.ordered_by_name
end

# GET /admin/speakers/1
def show; end

# GET /admin/speakers/new
def new
@speaker = Speaker.new
end

# GET /admin/speakers/1/edit
def edit
render_not_found unless @speaker
end

# POST /admin/speakers
def create
@speaker = Speaker.new(speaker_params)

respond_to do |format|
if @speaker.save
format.html do
redirect_to edit_admin_speaker_url(@speaker),
notice: 'Speaker was successfully created.'
end
else
format.html { render :new, status: :unprocessable_entity }
end
end
end

# PATCH/PUT /admin/speakers/1
def update
respond_to do |format|
if @speaker.update(speaker_params)
format.html do
redirect_to edit_admin_speaker_url(@speaker),
notice: 'Speaker was successfully updated.'
end
format.json { render :show, status: :ok, location: @speaker }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @speaker.errors, status: :unprocessable_entity }
end
end
end

# DELETE /admin/speakers/1
# def destroy
# @speaker.destroy

# respond_to do |format|
# format.html do
# redirect_to admin_speakers_url, notice: 'Speaker was successfully destroyed.'
# end
# end
# end

private

def authorize_event
authorize Event
end

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

# Only allow a list of trusted parameters through.
def speaker_params
params.require(:speaker).permit(
:name,
:bio,
:tagline,
:image_url,
:github,
:linkedin,
:mastodon,
:website,
:twitter,
:other,
)
end
end
end
6 changes: 6 additions & 0 deletions app/helpers/admin/speakers_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true
module Admin
module SpeakersHelper
#Add helpers
end
end
24 changes: 0 additions & 24 deletions app/javascript/packs/hello_react.jsx

This file was deleted.

38 changes: 38 additions & 0 deletions app/models/speaker.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,46 @@
# frozen_string_literal: true

class Speaker < ApplicationRecord
include HTTParty
SOCIAL_MEDIA_LINKS = %w[github linkedin mastodon twitter website other].freeze

has_many :event_speakers, dependent: :destroy
has_many :events, through: :event_speakers

validates :name, :bio, :image_url, presence: true
validate :links, :validate_social_media_brand
validate :url_exists?, if: ->(s) { s.links.compact_blank.present? }

store :links, accessors: SOCIAL_MEDIA_LINKS, coder: JSON

before_validation :format_links

scope :ordered_by_name, -> { order(:name) }

def validate_social_media_brand
return if links.blank? || links.keys.all? { |key| SOCIAL_MEDIA_LINKS.include?(key) }

errors.add(:links, 'This social media is not allowed')
end

def format_links
return if links.blank?

links.transform_keys!(&:downcase)
end

def url_exists?
links.each { |_, url| errors.add(:links, 'This url is not valid') unless url_valid?(url) }
end

def empty_links?
links.compact_blank.empty?
end

private

def url_valid?(url)
response = HTTParty.get(url)
response.code == 200
end
end
26 changes: 26 additions & 0 deletions app/policies/speaker_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true
class SpeakerPolicy < ApplicationPolicy
def index?
user.admin?
end

def new?
user.admin?
end

def create?
user.admin?
end

def edit?
user.admin?
end

def show?
edit?
end

def update?
user.admin?
end
end
2 changes: 1 addition & 1 deletion app/views/admin/events/_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%= form_for [:admin, @event.becomes(Event)] do |f| %>
<%= form_for [:admin, event.becomes(Event)] do |f| %>
<%= render 'layouts/admin/form_errors', object: f.object %>
<div class="field form-floating mb-4">
<%= f.text_field :title, class: "form-control" %>
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/events/edit.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="row">
<div class="col col-lg-6">
<h1>Edit event</h1>
<%=render 'form'%>
<%=render 'form', event: @event %>
</div>
</div>
63 changes: 33 additions & 30 deletions app/views/admin/events/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,42 +1,45 @@
<h1 class="mb-4">Event List</h1>
<div class="row">
<div class="col">
<%= link_to new_admin_event_path, class: "btn btn-primary btn-lg mb-3" do %>
<%= link_to new_admin_event_path, class: "btn btn-primary btn-md mb-4" do %>
Create new Event
<i class="bi bi-plus fw-semibold"></i>
<% end %>
</div>
</div>
<div class="row">
<div class="col">
<table class="table text-center">
<thead class="border-2">
<tr>
<th scope="col" class="p-3">Title</th>
<th scope="col" class="p-3">Type</th>
<th scope="col" class="p-3">Speakers</th>
<th scope="col" class="p-3">Date</th>
<th scope="col" class="p-3">Location</th>
<th scope="col" class="p-3">Description</th>
<th scope="col" class="p-3">Actions</th>
</tr>
</thead>
<tbody>
<% @events.each do |event| %>
<tr class="border-2">
<td class="p-3"><%= event.title %></td>
<td class="p-3"><%= event.type %></td>
<td class="p-3"><%= event.speakers.map(&:name).join(", ") %></td>
<td class="p-3"><%= event.date.strftime('%B %d, %Y %I:%M%p %:z') %></td>
<td class="p-3"><%= event.location %></td>
<td class="p-3"><%= truncate_html(event.description) %></td>
<td class="p-3">
<%= link_to 'Edit', edit_admin_event_path(event) %>
<%= link_to 'Delete', admin_event_path(event), method: :delete %>
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="table-responsive">
<table class="table table-sm text-center table-hover">
<thead class="border-2">
<tr class="table-primary">
<th scope="col" class="p-3">Title</th>
<th scope="col" class="p-3">Type</th>
<th scope="col" class="p-3">Speakers</th>
<th scope="col" class="p-3">Date</th>
<th scope="col" class="p-3">Location</th>
<th scope="col" class="p-3">Description</th>
<th scope="col" class="p-3">Actions</th>
</tr>
</thead>
<tbody>
<% @events.each do |event| %>

<tr class="border-2">
<td class="p-3"><%= event.title %></td>
<td class="p-3"><%= event.type %></td>
<td class="p-3"><%= event.speakers.map(&:name).join(", ") %></td>
<td class="p-3"><%= event.date.strftime('%B %d, %Y %I:%M%p %:z') %></td>
<td class="p-3"><%= event.location %></td>
<td class="p-3"><%= truncate_html(event.description) %></td>
<td class="p-3">
<%= link_to 'Edit', edit_admin_event_path(event) %>
<%= button_to "Delete", admin_event_url(event), form_class: "", class: "link-primary border-0 bg-transparent text-decoration-underline", method: :delete %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
2 changes: 1 addition & 1 deletion app/views/admin/events/new.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="row">
<div class="col col-lg-6">
<h1>New Event</h1>
<%= render 'form'%>
<%= render 'form', event: @event %>
</div>
</div>
Loading

0 comments on commit b96e0ca

Please sign in to comment.