Skip to content
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

Create Speaker module for Admin #182

Merged
merged 4 commits into from
Aug 16, 2023
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
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
Loading