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

Make learning materials page CRUD using the Rails Admin gem #87

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 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
1 change: 1 addition & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--require spec_helper
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ group :test do
# Use system testing [https://guides.rubyonrails.org/testing.html#system-testing]
gem 'capybara'
gem 'faker', '~> 3.1'
gem 'rspec-rails', '~> 6.1'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i myself prefer Rspec too, if we are going with Rspec, then we need to remove minitest, or make it clear which one we should be using on the project! @JudahSan @banta should we keep Rspec over Minitest?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw i'm aware that replacing minitest with rspec will also mean updating the github action to actually run the tests and move any minitest already written

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking forward to your opinions on this @banta and @JudahSan

gem 'selenium-webdriver'
gem 'simplecov', require: false # Code coverage analysis tool for ruby
gem 'webdrivers'
end

gem 'rails_admin', '~> 3.1'
gem 'sassc-rails'
53 changes: 53 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ GEM
globalid (>= 0.3.6)
activemodel (7.0.3)
activesupport (= 7.0.3)
activemodel-serializers-xml (1.0.2)
activemodel (> 5.x)
activesupport (> 5.x)
builder (~> 3.1)
activerecord (7.0.3)
activemodel (= 7.0.3)
activesupport (= 7.0.3)
Expand Down Expand Up @@ -149,6 +153,7 @@ GEM
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
diff-lcs (1.5.1)
digest (3.1.0)
docile (1.4.0)
dockerfile-rails (1.2.5)
Expand Down Expand Up @@ -180,6 +185,18 @@ GEM
jsbundling-rails (1.0.2)
railties (>= 6.0.0)
json (2.6.3)
kaminari (1.2.2)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.2)
kaminari-activerecord (= 1.2.2)
kaminari-core (= 1.2.2)
kaminari-actionview (1.2.2)
actionview
kaminari-core (= 1.2.2)
kaminari-activerecord (1.2.2)
activerecord
kaminari-core (= 1.2.2)
kaminari-core (1.2.2)
launchy (2.5.0)
addressable (~> 2.7)
letter_opener (1.8.1)
Expand All @@ -202,6 +219,7 @@ GEM
fugit (~> 1.0)
rails (>= 5.2)
msgpack (1.5.2)
nested_form (0.3.2)
net-imap (0.2.3)
digest
net-protocol
Expand Down Expand Up @@ -266,6 +284,12 @@ GEM
nokogiri (>= 1.6)
rails-html-sanitizer (1.4.2)
loofah (~> 2.3)
rails_admin (3.1.2)
activemodel-serializers-xml (>= 1.0)
kaminari (>= 0.14, < 2.0)
nested_form (~> 0.3)
rails (>= 6.0, < 8)
turbo-rails (~> 1.0)
railties (7.0.3)
actionpack (= 7.0.3)
activesupport (= 7.0.3)
Expand All @@ -283,6 +307,23 @@ GEM
actionpack (>= 5.0)
railties (>= 5.0)
rexml (3.2.5)
rspec-core (3.13.0)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (6.1.2)
actionpack (>= 6.1)
activesupport (>= 6.1)
railties (>= 6.1)
rspec-core (~> 3.13)
rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13)
rspec-support (~> 3.13)
rspec-support (3.13.1)
rubocop (1.51.0)
json (~> 2.3)
parallel (~> 1.10)
Expand All @@ -307,6 +348,14 @@ GEM
ffi (~> 1.12)
ruby_http_client (3.5.5)
rubyzip (2.3.2)
sassc (2.4.0)
ffi (~> 1.9)
sassc-rails (2.1.2)
railties (>= 4.0.0)
sassc (>= 2.0)
sprockets (> 3.0)
sprockets-rails
tilt
selenium-webdriver (4.2.0)
childprocess (>= 0.5, < 5.0)
rexml (~> 3.2, >= 3.2.5)
Expand Down Expand Up @@ -346,6 +395,7 @@ GEM
railties (>= 6.0.0)
strscan (3.0.3)
thor (1.2.1)
tilt (2.3.0)
timeout (0.3.0)
turbo-rails (1.1.1)
actionpack (>= 6.0.0)
Expand Down Expand Up @@ -406,10 +456,13 @@ DEPENDENCIES
premailer-rails (~> 1.12)
puma (~> 5.0)
rails (~> 7.0.3)
rails_admin (~> 3.1)
redis (~> 4.0)
rspec-rails (~> 6.1)
rubocop (~> 1.51.0)
rubocop-performance (~> 1.18)
rubocop-rails (~> 2.19.1)
sassc-rails
selenium-webdriver
sendgrid-actionmailer (~> 3.2)
simple_form (~> 5.1)
Expand Down
Binary file added app/assets/images/learningmaterialsthumbnail.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 24 additions & 15 deletions app/assets/stylesheets/mailgun_mails.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@
font-size: 14px;
}

/* Add CSS variable for repetitive colors */

:root {
--red: #D0021B;
--lightblue: #348eda;
--orange: #ff9f00;
--lightgreen: #68B90F;
}

img {
max-width: 100%;
}
Expand Down Expand Up @@ -136,15 +145,15 @@ p li, ul li, ol li {
LINKS & BUTTONS
------------------------------------- */
a {
color: #348eda;
color: var(--lightblue);
text-decoration: underline;
}

.btn-primary {
text-decoration: none;
color: #FFF;
background-color: #348eda;
border: solid #348eda;
background-color: var(--lightblue);
border: solid var(--lightblue);
border-width: 10px 20px;
line-height: 2em;
/* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
Expand All @@ -160,9 +169,9 @@ a {
.btn-warning {
text-decoration: none;
color: #FFF;
background-color: #ff9f00;
border: solid #ff9f00;
border-color: #ff9f00;
background-color: var(--orange);
border: solid var(--orange);
border-color: var(--orange);
border-width: 10px 20px;
line-height: 2em;
/* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
Expand All @@ -178,9 +187,9 @@ a {
.btn-success {
text-decoration: none;
color: #FFF;
background-color: #68B90F;
border: solid #68B90F;
border-color: #68B90F;
background-color: var(--lightgreen);
border: solid var(--lightgreen);
border-color: var(--lightgreen);
border-width: 10px 20px;
line-height: 2em;
/* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
Expand All @@ -196,9 +205,9 @@ a {
.btn-danger {
text-decoration: none;
color: #FFF;
background-color: #D0021B;
border: solid #D0021B;
border-color: #D0021B;
background-color: var(--red);
border: solid var(--red);
border-color: var(--red);
border-width: 10px 20px;
line-height: 2em;
/* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
Expand Down Expand Up @@ -257,13 +266,13 @@ a {
font-size: 16px;
}
.alert.alert-warning {
background-color: #FF9F00;
background-color: var(--orange);
}
.alert.alert-bad {
background-color: #D0021B;
background-color: var(--red);
}
.alert.alert-good {
background-color: #68B90F;
background-color: var(--lightgreen);
}

/* -------------------------------------
Expand Down
14 changes: 14 additions & 0 deletions app/controllers/learning_materials_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true
Nemwel-Boniface marked this conversation as resolved.
Show resolved Hide resolved

class LearningMaterialsController < ApplicationController
skip_before_action :authenticate_user!, only: %i[index]

def index
@learningmaterials = LearningMaterial.all
Nemwel-Boniface marked this conversation as resolved.
Show resolved Hide resolved
@learningmaterials_with_thumbnails = @learningmaterials.select do |learningmaterial|
learningmaterial.thumbnail.attached?
end
@random_learningmaterials = @learningmaterials_with_thumbnails.sample(2)
@learningmaterials_with_or_without_thumbnails = @learningmaterials - @random_learningmaterials
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@learningmaterials_with_or_without_thumbnails = @learningmaterials - @random_learningmaterials
@learning_materials_without_random = @learning_materials - @random_learning_materials

maybe this makes more sense? 🤷‍♂️ naming things is hard 😅

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this suggestion and yes naming things is really hard because there is never a "one right/ true way" to name things. The reason why it is named as "with or without thumbnails" is because it is supposed to hold all other Learning materials regardless of whether that specific learning material has an attached thumbnail or not. If this is renamed to your suggestion I am afraid it will lead to slight confusion later.

What do you think @denissellu ? 🤔

end
end
4 changes: 4 additions & 0 deletions app/helpers/learning_materials_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# frozen_string_literal: true

module LearningMaterialsHelper
end
15 changes: 15 additions & 0 deletions app/models/learning_material.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

class LearningMaterial < ApplicationRecord
# Associations
belongs_to :user
has_one_attached :thumbnail

# Enum
enum tag: { beginners: 0, intermediates: 1, experts: 2 }

# Validations
validates :tag, :learning_material_title, :learning_material_description, :learning_material_link, presence: true
validates :learning_material_link,
format: { with: URI::DEFAULT_PARSER.make_regexp(%w[http https]), message: :invalid_url }
end
1 change: 1 addition & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class User < ApplicationRecord
# Associations
has_many :users_chapters, dependent: :nullify
has_many :chapters, through: :users_chapters
has_many :learning_materials, dependent: :nullify

# Callbacks
before_create :set_defaults # Set model defaults before create
Expand Down
2 changes: 1 addition & 1 deletion app/views/layouts/_footer.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

<li><%= link_to 'Chapters', chapters_path %></li>

<li><%= link_to 'Learning materials', landing_learn_path %></li>
<li><%= link_to 'Learning materials', learning_materials_path %></li>

<% if FeatureFlag.find_by(name: 'projects').try(:enabled) %>
<li><%= link_to 'Projects', '#' %></li>
Expand Down
4 changes: 2 additions & 2 deletions app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
<li><a href="#">Projects</a></li>
<% end %>

<li><%= link_to 'Learning Materials', landing_learn_path %></li>
<li><%= link_to 'Learning Materials', learning_materials_path %></li>

<% if user_signed_in? %>
<li><%= button_to "Sign out", destroy_user_session_path, method: :delete %></li>
Expand Down Expand Up @@ -85,7 +85,7 @@
</a>
<% end %>

<%= link_to 'Learning Materials', landing_learn_path,
<%= link_to 'Learning Materials', learning_materials_path,
class: 'text-sm font-small text-gray-500 hover:text-red-600' %>
</nav>
<% if user_signed_in? %>
Expand Down
94 changes: 94 additions & 0 deletions app/views/learning_materials/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<% content_for(:title,"Learning Materials") %>
<% content_for(:description,"A list of ruby and ruby on rails learning resources compiled by the ARC community") %>

<section class="max-w-screen-xl mx-auto p-5 sm:p-10 md:p-16 pt-20">
<div class="pb-15">
<h1 style="color: #D0021B;" class="text-4xl sm:text-5xl md:text-6xl lg:text-7xl xl:text-8xl font-bold text-left">Featured Materials</h1>
</div>

<div class="grid grid-cols-1 md:grid-cols-2 gap-10 pt-7">
<% if @learningmaterials.empty? %>
<h2>There are no created learning materials yet</h2>
<% else %>
<% # Display the selected random records with thumbnails %>
<% @random_learningmaterials.each do |learningmaterial| %>
<div class="rounded overflow-hidden shadow-lg p-4 border-b-2 border-dashed border-black-600">
<a href="#"></a>
<div class="relative">
<div class="py-4" style="height: 300px;">
<img src="<%= url_for(learningmaterial.thumbnail) %>" class="w-full h-full object-cover rounded-lg">
</div>
<div class="text-sm absolute top-0 right-0 bg-indigo-600 px-4 text-white rounded-full h-16 w-16 flex items-center justify-center mt-3 mr-3 hover:bg-white hover:text-indigo-600 transition duration-500 ease-in-out">
<span class="font-bold"><%= learningmaterial.created_at.strftime("%b %d") %></span>
</div>
</div>
<div class="px-6 py-4 flex justify-between items-center">
<p class="font-semibold text-lg sm:text-xl md:text-2xl lg:text-3xl xl:text-4xl inline-block hover:text-indigo-600 transition duration-500 ease-in-out"><%= learningmaterial.learning_material_title %></p>
<p class="text-gray-500 text-sm sm:text-base md:text-lg lg:text-xl xl:text-2xl"><%= learningmaterial.tag %></p>
</div>
<div class="px-6 py-4 flex justify-between items-center">
<p class="py-2 text-base sm:text-lg md:text-xl lg:text-2xl xl:text-3xl font-normal"><%= learningmaterial.learning_material_description %></p>
</div>
<div class="px-6 py-4 flex flex-row items-center">
<span class="py-1 text-sm sm:text-base md:text-lg lg:text-xl xl:text-2xl font-regular mr-1">
<%= link_to "READ MORE HERE", learningmaterial.learning_material_link, class: "learningmaterialslink ml-1", target: "_blank", style: "color: #D0021B;" %>
</span>
</div>
</div>
<% end %>
<% end %>
</div>

<div class="pb-20 pt-20">
<h2 style="color: #D0021B;" class="text-2xl sm:text-3xl md:text-4xl lg:text-5xl xl:text-6xl font-bold text-left">Other Resources</h2>
</div>

<% # Display the remaining records regardless of whether it has thumbnail or not %>
<div class="grid grid-cols-1 md:grid-cols-3 gap-10 max-w-screen-xl mx-auto p-5 sm:p-10 md:p-16">
<% @learningmaterials_with_or_without_thumbnails.each do |learningmaterial| %>
<div class="rounded overflow-hidden shadow-lg p-4 border-b border-dotted border-gray-400">
<a href="#"></a>
<div class="relative">
<% if learningmaterial.thumbnail.attached? %>
<div class="py-4" style="height: 300px;">
<img src="<%= url_for(learningmaterial.thumbnail) %>" class="w-full h-full object-cover rounded-lg">
</div>
<% else %>
<div class="py-4" style="height: 300px;">
<img src="/assets/learningmaterialsthumbnail.jpeg" class="w-full h-full object-cover rounded-lg">
</div>
<% end %>
<div class="text-sm absolute top-0 right-0 bg-indigo-600 px-4 text-white rounded-full h-16 w-16 flex items-center justify-center mt-3 mr-3 hover:bg-white hover:text-indigo-600 transition duration-500 ease-in-out">
<span class="font-bold"><%= learningmaterial.created_at.strftime("%b %d") %></span>
</div>
</div>
<div class="px-6 py-4 flex justify-between items-center">
<p class="font-semibold text-lg sm:text-xl md:text-2xl lg:text-3xl xl:text-4xl inline-block hover:text-indigo-600 transition duration-500 ease-in-out"><%= learningmaterial.learning_material_title %></p>
<p class="text-gray-500 text-sm sm:text-base md:text-lg lg:text-xl xl:text-2xl"><%= learningmaterial.tag %></p>
</div>
<div class="px-6 py-4 flex justify-between items-center">
<p class="py-2 text-base sm:text-lg md:text-xl lg:text-2xl xl:text-3xl font-normal"><%= learningmaterial.learning_material_description %></p>
</div>
<div class="px-6 py-4 flex flex-row items-center">
<span class="py-1 text-sm sm:text-base md:text-lg lg:text-xl xl:text-2xl font-regular mr-1">
<%= link_to "READ MORE HERE", learningmaterial.learning_material_link, class: "learningmaterialslink ml-1", target: "_blank", style: "color: #D0021B;" %>
</span>
</div>
</div>
<% end %>
</div>

<div class="pb-20 pt-20">
<h2 style="color: #D0021B;" class="text-2xl sm:text-3xl md:text-4xl lg:text-5xl xl:text-6xl font-bold text-left">If you may not want the view above, here is a list of the same details shown above.</h2>
</div>

<ol type="1" start="1" class="max-w-md space-y-1 text-gray-500 dark:text-gray-400" style="list-style-type: decimal; padding-left: 20px;">
<% @learningmaterials.each do |learningmaterial| %>
<li class="py-2">
<span class="py-1 text-sm sm:text-base md:text-lg lg:text-xl xl:text-2xl font-regular mr-1">
<%= link_to learningmaterial.learning_material_title, learningmaterial.learning_material_link, class: "learningmaterialslink ml-1", target: "_blank", style: "color: #D0021B;" %> <span> - <%= learningmaterial.learning_material_description %> </span>
</span>
</li>
<% end %>
</ol>
</section>
Loading
Loading