Skip to content
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: 4 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,7 @@ Layout/TrailingWhitespace:

# require exactly one final newline at end of each file
Layout/TrailingEmptyLines:
Enabled: true
Enabled: true

RSpec/MultipleExpectations:
Max: 2
2 changes: 1 addition & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def logged_in?
def require_admin
unless current_user&.role == "admin"
flash[:alert] = "You do not have permission to do that."
redirect_to root_path
redirect_to dashboard_path
end
end

Expand Down
11 changes: 11 additions & 0 deletions app/controllers/dashboard_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
class DashboardController < ApplicationController
before_action :require_login

def index
@recent_tracks = Track.order(created_at: :desc).limit(5)
@recent_comments = Comment.order(created_at: :desc).limit(5)
end

private

def require_login
unless logged_in?
flash[:alert] = "Please log in to access the dashboard"
redirect_to login_path
end
end
end
4 changes: 4 additions & 0 deletions app/controllers/home_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class HomeController < ApplicationController
def index
end
end
24 changes: 24 additions & 0 deletions app/controllers/samples_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
class SamplesController < ApplicationController
before_action :require_admin

def new
@sample = Sample.new
@tracks = Track.order(:title)
end

def create
@sample = Sample.new(sample_params)
if @sample.save
redirect_to dashboard_path, notice: "Sample Connection created!"
else
@tracks = Track.order(:title)
render :new, status: :unprocessable_entity
end
end

private

def sample_params
params.require(:sample).permit(:derived_track_id, :source_track_id)
end
end
3 changes: 2 additions & 1 deletion app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ def new

def create
user = User.find_by(username: params[:username])

if user&.authenticate(params[:password])
session[:user_id] = user.id
session[:role] = user.role
redirect_to root_path, notice: "Logged in as #{user.username}"
redirect_to dashboard_path, notice: "Logged in as #{user.username}"
else
flash.now[:alert] = "Invalid username or password"
render :new, status: :unprocessable_entity
Expand Down
8 changes: 6 additions & 2 deletions app/controllers/tracks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,28 @@ def new

def create
@track = Track.new(track_params)
@track.user = User.find_by(username: "Twhite")
@track.user = current_user

if @track.save
redirect_to @track, notice: "Track Created!"
else
@artists = Artist.alphabetical
render :new, status: :unprocessable_entity
end
end

def edit
@track = Track.find(params[:id])
@artists = Artist.alphabetical
end

def update
@track = Track.find(params[:id])
@track.user = User.find_by(username: "Twhite")
@track.user = current_user
if @track.update(track_params)
redirect_to @track, notice: "Track Updated"
else
@artists = Artist.alphabetical
render :edit, status: :unprocessable_entity
end
end
Expand Down
22 changes: 22 additions & 0 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class UsersController < ApplicationController
def new
@user = User.new
end

def create
@user = User.new(user_params)
if @user.save
session[:user_id] = @user.id
redirect_to dashboard_path, notice: "Welcome, #{@user.username}!"
else
flash.now[:alert] = @user.errors.full_messages.to_sentence
render :new, status: :unprocessable_entity
end
end

private

def user_params
params.require(:user).permit(:username, :email, :password, :password_confirmation)
end
end
2 changes: 2 additions & 0 deletions app/helpers/home_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module HomeHelper
end
2 changes: 2 additions & 0 deletions app/helpers/users_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module UsersHelper
end
2 changes: 1 addition & 1 deletion app/models/artist.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class Artist < ApplicationRecord
has_many :tracks, dependent: :destroy

validates :name, presence: true
validates :name, presence: true, uniqueness: true

# alpha scope
scope :alphabetical, -> { order("LOWER(name) ASC") }
Expand Down
25 changes: 23 additions & 2 deletions app/models/sample.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,27 @@ class Sample < ApplicationRecord

has_many :sample_segments, dependent: :destroy

# TODO Validate later sampler_entry_id can not be equal sampled_entry_id
# AKA a song can not sample itself or be sampled by itself
validates :derived_track_id, presence: true
validates :source_track_id, presence: true
validate :no_self_sampling
validate :no_sampling_from_future

# a source id cannot be equal to a derived id on sample join table
def no_self_sampling
if derived_track_id == source_track_id
errors.add(:base, "A track cannot sample itself")
end
end

# check sourceYear exist, derivedYear exist, then if derived is less than source throw error
def no_sampling_from_future
if source_track&.year && derived_track&.year && derived_track&.year < source_track&.year
errors.add(:base, "A track cannot sample from the future")
end
end

# behavior methods
def description
"#{derived_track.title} samples #{source_track.title}"
end
end
16 changes: 15 additions & 1 deletion app/models/track.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ class Track < ApplicationRecord
source: :derived_track

validates :title, presence: true
validates :year, presence: true
validates :year, numericality: { greater_than_or_equal_to: 1900, less_than_or_equal_to: Date.current.year }
validates :bpm, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true

# behavior methods

def formatted_title
"#{title} (#{year})"
end

def sample_count
samples_used.count
end

def sampled_by_count
sampled_by_tracks.count
end
end
10 changes: 8 additions & 2 deletions app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
class User < ApplicationRecord
has_many :tracks
has_many :comments
# TODO gameplan user.delete, what happens to their entries and comments.
# future nullify user id on orphaned tracks?
has_many :comments, dependent: :destroy

has_secure_password

after_initialize :set_default_role, if: :new_record?

def set_default_role
self.role ||= "user"
end

validates :email, presence: true, uniqueness: true
validates :username, presence: true, uniqueness: true

Expand Down
20 changes: 16 additions & 4 deletions app/views/dashboard/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
<h1>Dashboard</h1>

<% if flash[:alert] %>
<div style="color:red; text-align:center; margin-bottom: 20px;">
<%= flash[:alert] %>
</div>
<% end %>

<h2>Recent Tracks</h2>
<ul>
Expand All @@ -22,6 +27,13 @@
<% end %>
</ul>

<p>
<%= link_to "Add New Track", new_track_path %>
</p>
<div style="text-align:left; margin-top: 20px;">
<%= link_to "Add New Track", new_track_path,
style: "padding: 10px 20px; background-color: #007bff; color: white; text-decoration: none; border-radius: 5px; margin-right: 10px;" %>

<%= link_to "Add New Sample Connection", new_sample_path,
style: "padding: 10px 20px; background-color: #28a745; color: white; text-decoration: none; border-radius: 5px; margin-right: 10px;" %>

<%= link_to "View All Tracks", tracks_path,
style: "padding: 10px 20px; background-color: #6c757d; color: white; text-decoration: none; border-radius: 5px;" %>
</div>
16 changes: 16 additions & 0 deletions app/views/home/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div style="text-align:center; margin-top: 100px;">
<h1>Sample DB</h1>
<p>A database of who sampled who.</p>
<div style="margin-top: 30px;">

<%= link_to "View All Tracks", tracks_path, class: "btn",
style: "padding: 10px 20px; background-color: #6c757d; color: white; text-decoration: none; border-radius: 5px; margin-right: 10px;" %>

<%= link_to "Log In", login_path, class: "btn",
style: "padding: 10px 20px; background-color: #007bff; color: white; text-decoration: none; border-radius: 5px; margin-right: 10px;" %>

<%= link_to "Sign Up", signup_path, class: "btn",
style: "padding: 10px 20px; background-color: #28a745; color: white; text-decoration: none; border-radius: 5px;" %>

</div>
</div>
60 changes: 41 additions & 19 deletions app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,44 @@
<%= javascript_importmap_tags %>
</head>

<body>
<% if flash[:notice] %>
<p class="notice"><%= flash[:notice] %></p>
<% end %>

<% if flash[:alert] %>
<p class="alert"><%= flash[:alert] %></p>
<% end %>

<% if logged_in? %>
<p>Logged in as <%= current_user.username %></p>
<%= button_to "Logout", logout_path, method: :delete %>
<% else %>
<%= link_to "Login", login_path %>
<% end %>

<%= yield %>
</body>
</html>
<body>
<header>
<div style="display: flex; justify-content: space-between; align-items: center; padding: 10px;">
<!-- Left: Login / Logout -->
<div>
<% if logged_in? %>
<%= button_to "Logout", logout_path, method: :delete %>
<% else %>
<%= link_to "Login", login_path %>
<% end %>
</div>

<!-- Center: Logged in as ... -->
<div>
<% if logged_in? %>
<p>Logged in as <%= current_user.username %></p>
<% end %>
</div>

<!-- Right: Dashboard -->
<div>
<%= link_to "Dashboard", dashboard_path %>
</div>
</div>
</header>

<%= yield %>

<% if flash[:notice] %>
<div style="color: green; text-align: center; margin: 10px 0;">
<%= flash[:notice] %>
</div>
<% end %>

<% if flash[:alert] %>
<div style="color: red; text-align: center; margin: 10px 0;">
<%= flash[:alert] %>
</div>
<% end %>
</body>
</html>
27 changes: 27 additions & 0 deletions app/views/samples/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<h1>Add Sample Connection</h1>

<%= form_with model: @sample, local: true do |f| %>
<% if @sample.errors.any? %>
<div style="color:red;">
<ul>
<% @sample.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>

<div style="display: flex; gap: 20px; align-items: center; margin-bottom: 20px;">
<div>
<%= f.label :derived_track_id, "New Track" %><br>
<%= f.collection_select :derived_track_id, @tracks, :id, :title, prompt: "Select sampler" %>
</div>

<div>
<%= f.label :source_track_id, "Original Source" %><br>
<%= f.collection_select :source_track_id, @tracks, :id, :title, prompt: "Select sampled track" %>
</div>
</div>

<%= f.submit "Create Sample Connection" %>
<% end %>
33 changes: 20 additions & 13 deletions app/views/sessions/new.html.erb
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
<h1>Login</h1>
<div style="text-align:center; margin-top: 100px;">
<h2>Log In</h2>

<%= form_with url: login_path, local: true do |form| %>
<div>
<%= form.label :username %><br>
<%= form.text_field :username %>
</div>

<div>
<%= form.label :password %><br>
<%= form.password_field :password %>
</div>
<%= form_with url: login_path, local: true do |form| %>

<div>
<%= form.submit "Login" %>
<% if flash[:alert] %>
<div style="color:red; text-align:center; margin-bottom:20px;">
<p><%= flash[:alert] %></p>
</div>
<% end %>

<div style="margin:10px 0;">
<%= form.label :username %><br>
<%= form.text_field :username %>
</div>

<div style="margin:10px 0;">
<%= form.label :password %><br>
<%= form.password_field :password %>
</div>

<%= form.submit "Log In", class: "btn btn-primary" %>
<% end %>
</div>
Loading