Skip to content

Commit

Permalink
Implements initial implementation of users admin CRUD (#46)
Browse files Browse the repository at this point in the history
* [#7] Adds route to admin users, and link to admin user index to the layout.

* [#7] removes password_digest column from users table.

* [#7] Adds Admin users index and show pages.

* [#7] Removes to_csv method from User model.

* [#6] Fixes a crash on facility card component

* [#6] Removes unneeded columns from facilities. (r_pets, r_id, r_cart, r_phone, r_wifi, and *_note columns).

* [#7] Adds Vancouver and New Westminster zones to seeds.

* [#7] Implements fake_data:users and fake_data:facilities rake tasks to help populate development database.

* [#7] Implements ability to create, update and delete users.

* [#6] Fixes a crash on Facility validation when any of the clean_data columns has a nil value.

* [#7] Improves view components for Status of Users and Facilities.

* [#7] Refactors User form to shared partials.

* [#7] Implements ability to Reset Password of users.

* [#7] Implements website_url method on Facility model to handle website column content.

* [#7] Fixes a potential mass-assignment vulnerability as pointed by brakeman.
  • Loading branch information
fabionl authored Nov 28, 2021
1 parent c0de905 commit 3facc40
Show file tree
Hide file tree
Showing 37 changed files with 803 additions and 74 deletions.
49 changes: 21 additions & 28 deletions app/components/facilities/card_component/card_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,30 @@
<header class="card-header level mb-1">
<div class="level-left">
<div class="card-header-title">
<%= link_to admin_facility_path(facility) do %>
<span class="icon-text">
<% if facility.verified? %>
<span class="icon has-text-success">
<i class="fas fa-check-square"></i>
</span>
<% else %>
<span class="icon has-text-danger">
<i class="fas fa-times"></i>
</span>
<% end %>

<span class="icon-text">
<% if facility.verified? %>
<span class="icon has-text-success">
<i class="fas fa-check-square"></i>
</span>
<% else %>
<span class="icon has-text-danger">
<i class="fas fa-times"></i>
<span>
<%= facility.name %>
</span>
<% end %>

<span>
<%= facility.name %>
</span>
</span>
<% end %>

</div>
</div>

<div class="level-right">
<div class="field is-grouped">
<div class="control">

<%= label_tag :verified, facility.verified? ? 'Live' : 'Pending Reviews' %>
</div>

Expand All @@ -40,6 +40,8 @@
</div>
<div class="dropdown-menu" id="dropdown-menu6" role="menu">
<div class="dropdown-content">
<%= link_to 'Show', admin_facility_path(facility), class: "dropdown-item" %>
<%= link_to 'Edit', edit_admin_facility_path(facility), class: "dropdown-item" %>

<a class="dropdown-item">Delete</a>
Expand All @@ -62,18 +64,18 @@

<div class="column">
Services:
<% if facility.services.blank? %>
<% if facility.facility_services.blank? %>
<span class="tag is-danger">None</span>
<% else %>
<% facility.services.compact_blank.each do |service| %>
<% facility.facility_services.compact_blank.each do |service| %>
<span class="tag is-light"><%= service.name %></span>
<% end %>
<% end %>

<br/>
<div class='svg-icons'>
<span>Welcomes:</span>
<% if facility.welcomes.blank? %>
<% if facility.facility_welcomes.blank? %>
<span class='tag is-danger'>None</span>
<% else %>
<% facility.facility_welcomes.each do |welcome| %>
Expand All @@ -91,17 +93,8 @@
<% if facility.user.blank? %>
<%= tag.span 'Not Present', class: 'tag is-danger'%>
<% else %>
<% if facility.user.verified? %>
<span class="icon is-small">
<i class="fas fa-user-check"></i>
</span>
<%= tag.span 'Verified', class: 'tag is-light'%>
<% else %>
<span class="icon is-small">
<i class="fas fa-user-times"></i>
</span>
<%= tag.span 'Not Verified', class: 'tag is-danger'%>
<% end %>
<%= render Users::StatusComponent.new(facility.user, show_title: true) %>

<br/>
<%= facility.user.name %> |
<%= facility.user.email %>
Expand Down
2 changes: 1 addition & 1 deletion app/components/facilities/show_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def card_id
end

def link_to_website
link_to facility.website, URI::HTTP.build({ host: facility.website }).to_s
link_to facility.website_url, facility.website_url, target: "_blank", rel: "noopener"
end

def status_icon
Expand Down
12 changes: 1 addition & 11 deletions app/components/facilities/show_component/show_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,7 @@
<% if user.blank? %>
<%= tag.span 'Not Present', class: 'tag is-danger'%>
<% else %>
<% if user.verified? %>
<span class="icon is-small">
<i class="fas fa-user-check"></i>
</span>
<%= tag.span 'Verified', class: 'tag is-light'%>
<% else %>
<span class="icon is-small">
<i class="fas fa-user-times"></i>
</span>
<%= tag.span 'Not Verified', class: 'tag is-danger'%>
<% end %>
<%= render Users::StatusComponent.new(user, show_title: true) %>

<br/>
<%= user.name %> |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<div id="navbarBasicExample" class="navbar-menu">
<div class="navbar-start">
<%= link_to 'Facilities', admin_facilities_path, class: 'navbar-item' %>
<%= link_to 'Users', admin_users_path, class: 'navbar-item' %>

<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
Expand Down
11 changes: 8 additions & 3 deletions app/components/shared/card_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,24 @@ def classes
end

class ButtonComponent < ViewComponent::Base
def initialize(title:, path:)
def initialize(title:, path:, method: :get, icon_class: "fa-pen")
super()

@title = title
@path = path
@method = method
@icon_class = icon_class
end

def render?
@title.present? && @path.present?
end

def call
link_to @path, class: "button" do
params = { class: "button" }
params[:method] = @method if @method.present? && @method != :get

link_to @path, params do
button_content
end
end
Expand All @@ -63,7 +68,7 @@ def button_content

def edit_icon
tag.span(class: "icon") do
tag.i class: "fas fa-pen"
tag.i class: "fas #{@icon_class}"
end
end
end
Expand Down
8 changes: 6 additions & 2 deletions app/components/shared/status_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ def call
end

def call_icon
tag.span class: "icon" do
tag.span class: "icon #{color_classes}" do
tag.i class: "fas #{size_classes} #{status_classes}"
end
end

def call_title
tag.span class: "icon-text has-text" do
tag.span class: "icon-text #{color_classes}" do
call_icon + tag.span(title)
end
end
Expand All @@ -48,6 +48,10 @@ def status_classes
STATUS_CLASSES[status]
end

def color_classes
nil
end

def status
@status ? :on : :off
end
Expand Down
15 changes: 15 additions & 0 deletions app/components/users/show_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

class Users::ShowComponent < ViewComponent::Base
attr_reader :user

def initialize(user:)
super()

@user = user
end

def card_id
dom_id(user)
end
end
59 changes: 59 additions & 0 deletions app/components/users/show_component/show_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<div class='columns'>
<div class='column'>
<%= render Shared::CardComponent.new(title: 'User Details') do |card| %>
<% card.button(title: 'Reset Password', path: new_admin_user_password_path(user)) %>
<% card.button(title: 'Edit', path: edit_admin_user_path(user)) %>
<% card.button(title: 'Delete', path: admin_user_path(user.id), method: :delete, icon_class: 'fa-trash-alt') %>

<table class='table'>
<tr>
<th>Name:</th>
<td><%= user.name %></td>
</tr>

<tr>
<th>Email:</th>
<td><%= user.email %></td>
</tr>

<tr>
<th>Organization:</th>
<td><%= user.organization %></td>
</tr>

<tr>
<th>Phone Number:</th>
<td><%= user.phone_number %></td>
</tr>
</table>
<% end %>
</div>

<div class='column'>
<!-- Descriptions -->
<%= render Shared::CardComponent.new(title: 'Info') do |card| %>
<table class='table'>
<tr>
<th>Status</th>
<td>
<%= render Users::StatusComponent.new(user, show_title: true) %>
</td>
</tr>

<tr>
<th>Admin:</th>
<td><%= user.admin.to_s.titleize %></td>
</tr>

<tr>
<th>Last Updated</th>
<td>
<time datetime="<%= user.updated_at %>">
<%= user.updated_at %>
</time>
</td>
</tr>
</table>
<% end %>
</div>
</div>
67 changes: 67 additions & 0 deletions app/components/users/status_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# frozen_string_literal: true

class Users::StatusComponent < Shared::StatusComponent
STATUS_CLASSES = {
verified: "fa-user-check",
not_verified: "fa-user-times"
}.freeze

COLOR_CLASSES = {
verified: "has-text-info-dark",
not_verified: "has-text-danger-dark"
}.freeze

SIZE_CLASSES = {
large: "fa-lg"
}.freeze

attr_reader :user

def initialize(user, show_title: false, size: :large)
super(nil, show_title: show_title, size: size)

@user = user
# # Overrides status from superclass
@status = user.verified? ? :verified : :not_verified
end

# def call
# @show_title.present? ? call_title : call_icon
# end
#
# def call_icon
# tag.span class: "icon" do
# tag.i class: "fas #{size_classes} #{status_classes}"
# end
# end
#
# def call_title
# tag.span class: "icon-text has-text" do
# call_icon + tag.span(title)
# end
# end

private

# def size_classes
# SIZE_CLASSES[@size]
# end

# Overrides superclass
def title
@status.to_s.titleize
# @status ? "Yes" : "No"
end

def status_classes
STATUS_CLASSES[status]
end

def color_classes
COLOR_CLASSES[status]
end

def status
user.verified? ? :verified : :not_verified
end
end
34 changes: 34 additions & 0 deletions app/components/users/table_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
class Users::TableComponent < ViewComponent::Base
attr_reader :users

def initialize(users:)
super()

@users = users
end

class UserRowComponent < ViewComponent::Base
attr_reader :user, :table_component

def initialize(user, table_component:)
super()

@user = user
@table_component = table_component
end

def more_menu_component
@more_menu_component ||= MoreMenuComponent.new(user: user)
end
end

class MoreMenuComponent < ViewComponent::Base
attr_reader :user

def initialize(user: nil)
super()

@user = user
end
end
end
19 changes: 19 additions & 0 deletions app/components/users/table_component/more_menu_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<div class="dropdown is-hoverable is-right">
<div class="dropdown-trigger">
<button class="button no-border transparent" aria-haspopup="true" aria-controls="dropdown-menu4">
<span class="icon is-small">
<i class="fas fa-ellipsis-v"></i>
</span>
</button>
</div>
<div class="dropdown-menu" role="menu">
<div class="dropdown-content position-relative stretched-link">
<div class="dropdown-item">
<span class="icon is-small">
<i class="fas fa-info-circle"></i>
</span>
<%#= distribution.show_link %>
</div>
</div>
</div>
</div>
Loading

0 comments on commit 3facc40

Please sign in to comment.