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
26 changes: 26 additions & 0 deletions app/controllers/admin_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,28 @@ def update_creator_status
render json: user, root: :data, status: :ok, meta: { message: "Creator status updated!" }
end

def feature_course
course = Course.non_deleted_courses.find(feature_course_params[:course_id])

unless course.publish_status_published? && course.course_status_active? && !course.private?
raise Errors::BaseError.new(message: "Only published, active, public courses can be featured", status: 400)
end

# Adding an already-featured course just refreshes its featured date (bumping it up the list)
course.update!(featured_at: Time.now)

render json: course, root: :data, status: :ok, meta: { message: "Course added to featured list!" }
end

def unfeature_course
course = Course.non_deleted_courses.find(feature_course_params[:course_id])

# Idempotent: removing a course that isn't featured is a no-op
course.update!(featured_at: nil)

render json: course, root: :data, status: :ok, meta: { message: "Course removed from featured list!" }
end

def dummy_course_toggle
course = Course.find(dummy_course_toggle_params[:course_id])

Expand Down Expand Up @@ -426,4 +448,8 @@ def update_creator_status_params
def dummy_course_toggle_params
params.permit(:course_id, :undo_dummy_status)
end

def feature_course_params
params.permit(:course_id)
end
end
2 changes: 1 addition & 1 deletion app/controllers/auth_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def login_creator

# If the user is not a creator or admin, they cannot login here
if user.creator_status_none? && user.user_type != :admin
raise Errors::AuthenticationError.new(message: "You are not an approved creator, please use the usual StudyRound login")
raise Errors::AuthenticationError.new(message: "You are not a creator. Please visit https://app.studyround.com to onboard as a creator.")
end

if user && user.authenticate(login_params[:password])
Expand Down
12 changes: 10 additions & 2 deletions app/controllers/courses_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class CoursesController < ApplicationController
include CardTransactionHelper

before_action :default_12_page_size, only: [:index, :per_category, :enrolled_courses, :search, :my_courses, :tests, :purchased_courses, :purchased_tests, :created_courses]
skip_before_action :authorize!, only: [:index, :show, :categorised, :similar_courses, :top_courses, :trending_courses, :search, :dummy_courses]
skip_before_action :authorize!, only: [:index, :show, :categorised, :similar_courses, :top_courses, :trending_courses, :search, :dummy_courses, :featured_courses]
before_action :check_creators_consent, only: [:create]
before_action :load_creators_course, only: [:update, :publish, :destroy]

Expand Down Expand Up @@ -57,7 +57,7 @@ def create
raise Errors::ForbiddenError.new(message: "You have reached the maximum number of courses you can create")
end
else
# Do nothing
raise Errors::ForbiddenError.new(message: "You are not a creator. Please visit https://app.studyround.com to onboard as a creator.")
end

course_params = prepare_received_course_params(create_course_params)
Expand Down Expand Up @@ -387,6 +387,14 @@ def dummy_courses
render json: paginated_courses, root: :data, meta: paginated_meta(paginated_courses)
end

def featured_courses
# Curated courses for the dashboard, ordered by most recently featured
courses = Course.featured_courses

paginated_courses = paginate(courses, params)
render json: paginated_courses, root: :data, meta: paginated_meta(paginated_courses)
end

private

def load_creators_course
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/questions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def create
raise Errors::ForbiddenError.new(message: "You have reached the maximum number of questions for this course")
end
else
# Do nothing
raise Errors::ForbiddenError.new(message: "You are not a creator. Please visit https://app.studyround.com to onboard as a creator.")
end

draft = create_draft(create_question_params)
Expand Down
3 changes: 3 additions & 0 deletions app/models/course.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class Course < ApplicationRecord

scope :published_active_or_dummy_courses, -> { published_active_courses.or(dummy_courses) }

# Curated, admin-featured courses for the dashboard. Ordered by most recently featured first.
scope :featured_courses, -> { published_active_courses.where.not(featured_at: nil).order(featured_at: :desc) }

scope :filtered_by_search, -> (search) { where('title ILIKE ?', "%#{search}%") }

# This doesn't provide unique results, so we're using the other one. Using distinct also fails on some queries.
Expand Down
3 changes: 3 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
end

get '/courses/categorised', to: "courses#categorised"
get '/courses/featured', to: "courses#featured_courses"
get '/courses/top', to: "courses#top_courses"
get '/courses/trending', to: "courses#trending_courses"
get '/courses/recent', to: "courses#recent_courses"
Expand Down Expand Up @@ -155,6 +156,8 @@
patch '/admin/update-result', to: "admin#update_result"
patch '/admin/update-creator-status', to: "admin#update_creator_status"
patch '/admin/dummy-course-toggle', to: "admin#dummy_course_toggle"
post '/admin/feature-course', to: "admin#feature_course"
delete '/admin/feature-course', to: "admin#unfeature_course"

post '/automation/assign-course', to: "automation#assign_course"
post '/automation/create-course', to: "automation#create_course"
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20260607175212_add_featured_at_to_courses.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddFeaturedAtToCourses < ActiveRecord::Migration[5.2]
def change
add_column :courses, :featured_at, :datetime
end
Comment on lines +2 to +4
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2026_03_08_142256) do
ActiveRecord::Schema.define(version: 2026_06_07_175212) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -136,6 +136,7 @@
t.datetime "last_publish_date"
t.integer "rating_count", default: 0
t.boolean "invite_only", default: false
t.datetime "featured_at"
t.index ["creator_id"], name: "index_courses_on_creator_id"
t.index ["title"], name: "index_courses_on_title"
end
Expand Down