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

3845 Add E-Learning functionality to website #3915

Open
wants to merge 21 commits into
base: develop
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ Metrics/BlockLength:
- 'config/environments/production.rb'
- 'config/routes.rb'
- 'db/migrate/20180828145628_vanity_migration.rb'
- 'db/seeds.rb'
- 'features/support/puffing_billy.rb'
- 'lib/tasks/cucumber.rake'
- 'spec/controllers/application_controller_spec.rb'
Expand Down Expand Up @@ -224,6 +225,7 @@ Metrics/MethodLength:
- 'db/migrate/20140914202645_create_activities.rb'
- 'db/migrate/20161103011445_create_friendly_id_slugs.rb'
- 'db/migrate/20180828145628_vanity_migration.rb'
- 'db/migrate/20230309172525_rolify_create_roles.rb'
- 'db/migrate/20230314192607_create_active_storage_tables.active_storage.rb'
- 'features/step_definitions/basic_steps.rb'
- 'features/step_definitions/contained_search_steps.rb'
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ gem 'rack-timeout'
gem 'rails_autolink'
gem 'recaptcha', require: 'recaptcha/rails'
gem 'redcarpet'
gem 'rolify'
gem 'ruby-gitter'
gem 'sass-rails', '>= 5'
gem 'seed_dump'
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ GEM
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
rexml (3.2.5)
rolify (6.0.1)
rspec (3.12.0)
rspec-core (~> 3.12.0)
rspec-expectations (~> 3.12.0)
Expand Down Expand Up @@ -873,6 +874,7 @@ DEPENDENCIES
rb-readline
recaptcha
redcarpet
rolify
redis
rspec-activemodel-mocks
rspec-html-matchers
Expand Down
8 changes: 8 additions & 0 deletions app/assets/stylesheets/global/users.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@
@extend .user-skills;
}

.user-roles {
@extend .user-skills;
label {
display: inline-block;
padding-left: 5px;
}
}

.user-summary {
overflow: hidden;

Expand Down
13 changes: 13 additions & 0 deletions app/controllers/courses_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

class CoursesController < ApplicationController
def create
@course = Course.create(course_params)
end

private

def course_params
params.require(:course).permit(:title, :description, :status, :user_id, :slack_channel_name)
end
end
19 changes: 19 additions & 0 deletions app/models/course.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

class Course < ApplicationRecord
extend FriendlyId
include Filterable
friendly_id :title, use: %i(slugged history)

validates :title, :description, :status, presence: true
validates :description, presence: true, length: { minimum: 5 }

belongs_to :user, optional: true
include UserNullable

scope :active, -> { where('status ILIKE ?', 'active').order(:title) }

def slack_channel
"https://agileventures.slack.com/app_redirect?channel=#{slack_channel_name}"
end
end
17 changes: 17 additions & 0 deletions app/models/role.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

class Role < ApplicationRecord
has_many :users, through: :users_roles

belongs_to :resource,
polymorphic: true,
optional: true

validates :resource_type,
inclusion: { in: Rolify.resource_types },
allow_nil: true

validates :name, presence: true

scopify
end
10 changes: 9 additions & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# frozen_string_literal: true

class User < ApplicationRecord
rolify
acts_as_paranoid

after_validation :geocode, if: ->(obj) { obj.last_sign_in_ip_changed? }
after_create :assign_default_role

include Filterable

extend Forwardable
Expand Down Expand Up @@ -35,7 +39,6 @@ class User < ApplicationRecord
extend FriendlyId
friendly_id :display_name, use: :slugged

after_validation :geocode, if: ->(obj) { obj.last_sign_in_ip_changed? }
# after_validation -> { KarmaCalculator.new(self).perform }

has_many :authentications, dependent: :destroy
Expand All @@ -45,9 +48,14 @@ class User < ApplicationRecord
has_many :event_instances
has_many :commit_counts
has_many :status
has_many :courses

has_many :subscriptions, autosave: true

def assign_default_role
add_role(:student) if roles.blank?
end

# ultimately replacing the field stripe_customer
def stripe_customer_id
subscription = current_subscription
Expand Down
13 changes: 13 additions & 0 deletions app/views/users/profile/_detail.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<% if presenter.contributed? %>
<li class="<%= activity_tab(param_tab)%>"><a href="#activity" data-toggle="tab">Activity</a></li>
<% end %>
<li><a href="#roles" data-toggle="tab">Roles</a></li>
</ul>
<div id="tab-content" class="tab-content" style="background: #fff;">

Expand Down Expand Up @@ -47,6 +48,18 @@
</section>
</div>
<% end %>
<div class="tab-pane" id="roles">
<section class="user-roles">
<h4>Roles</h4>
<ul>
<%= collection_check_boxes :user, :role_ids, Role.all, :id, :name do |b| %>
<li>
<%= b.check_box %> <%= b.label %>
</li>
<% end %>
</ul>
</section>
</div>

<% if presenter.contributed? %>
<div class="tab-pane <%= activity_tab(param_tab) %>"id="activity">
Expand Down
12 changes: 12 additions & 0 deletions config/initializers/rolify.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

Rolify.configure do |config|
# By default ORM adapter is ActiveRecord. uncomment to use mongoid
# config.use_mongoid

# Dynamic shortcuts for User class (user.is_admin? like methods). Default is: false
# config.use_dynamic_shortcuts

# Configuration to remove roles from database once the last resource is removed. Default is: true
# config.remove_role_if_empty = false
end
16 changes: 16 additions & 0 deletions db/migrate/20230302160750_create_courses.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

class CreateCourses < ActiveRecord::Migration[7.0]
def change
create_table :courses do |t|
t.string :title
t.text :description
t.string :slug, null: false
t.integer :user_id
t.string :status
t.string :slack_channel_name
t.timestamps
end
add_index :courses, :user_id
end
end
20 changes: 20 additions & 0 deletions db/migrate/20230309172525_rolify_create_roles.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

class RolifyCreateRoles < ActiveRecord::Migration[7.0]
def change
create_table(:roles) do |t|
t.string :name
t.references :resource, polymorphic: true
t.timestamps
end

create_table(:users_roles, id: false) do |t|
t.references :user
t.references :role
t.timestamps
end

add_index(:roles, %i(name resource_type resource_id))
add_index(:users_roles, %i(user_id role_id))
end
end
32 changes: 32 additions & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@
t.index ["user_id"], name: "index_commit_counts_on_user_id"
end

create_table "courses", force: :cascade do |t|
t.string "title"
t.text "description"
t.string "slug", null: false
t.integer "user_id"
t.string "status"
t.string "slack_channel_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_courses_on_user_id"
end

create_table "documents", id: :serial, force: :cascade do |t|
t.string "title"
t.text "body"
Expand Down Expand Up @@ -269,6 +281,16 @@
t.index ["slack_channel_id", "project_id"], name: "slack_channel_name", unique: true
end

create_table "roles", force: :cascade do |t|
t.string "name"
t.string "resource_type"
t.bigint "resource_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id"
t.index ["resource_type", "resource_id"], name: "index_roles_on_resource"
end

create_table "slack_channels", force: :cascade do |t|
t.string "environment"
t.string "code"
Expand Down Expand Up @@ -369,6 +391,16 @@
t.index ["slug"], name: "index_users_on_slug", unique: true
end

create_table "users_roles", id: false, force: :cascade do |t|
t.bigint "user_id"
t.bigint "role_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["role_id"], name: "index_users_roles_on_role_id"
t.index ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id"
t.index ["user_id"], name: "index_users_roles_on_user_id"
end

create_table "versions", id: :serial, force: :cascade do |t|
t.string "item_type", null: false
t.integer "item_id", null: false
Expand Down
25 changes: 24 additions & 1 deletion db/seeds.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

klasses = [Project, Document, User, Subscription, Karma, Plan, Article, Event, EventInstance, Karma]
klasses = [Project, Document, User, Subscription, Karma, Plan, Article, Event, EventInstance, Karma, Course]
old_counts = klasses.map(&:count)
should_prompt = old_counts.min.positive?

Expand Down Expand Up @@ -77,6 +77,20 @@ def get_country
)

puts 'Created default projects'

u.courses.create!(
title: 'OpenSource',
description: 'How to contribute to open source projects.',
status: 'Active'
)

u.courses.create!(
title: 'GitCourse',
description: 'Learn how to use git and github.',
status: 'Active'
)

puts 'Created default courses'
break
elsif %w(n no).include?(response)
break
Expand Down Expand Up @@ -108,6 +122,15 @@ def get_country
)
end
end

3.times do
p = u.courses.create(
title: Faker::Educator.course_name,
description: Faker::TvShows::GameOfThrones.quote,
status: 'active',
created_at: 1.month.ago
)
end
end

# Premium Users
Expand Down
10 changes: 10 additions & 0 deletions spec/factories/courses.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

FactoryBot.define do
factory :course do
sequence(:title) { |n| "Course #{n}" }
sequence(:slug) { |n| "course-#{n}" }
description { 'Warp fields stabilize.' }
status { 'active' }
end
end
7 changes: 7 additions & 0 deletions spec/factories/roles.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

FactoryBot.define do
factory :role do
name { 'MyString' }
end
end
30 changes: 30 additions & 0 deletions spec/models/course_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

require 'course'

RSpec.describe Course, type: :model do
it { is_expected.to belong_to(:user).optional(true) }

context '#save' do
subject { build_stubbed(:course) }

it 'should be a valid with all the correct attributes' do
expect(subject).to be_valid
end

it 'should be invalid without title' do
subject.title = ''
expect(subject).to_not be_valid
end

it 'should be invalid without description' do
subject.description = ''
expect(subject).to_not be_valid
end

it 'should be invalid without status' do
subject.status = ''
expect(subject).to_not be_valid
end
end
end
18 changes: 18 additions & 0 deletions spec/models/role_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe Role, type: :model do
context '#save' do
subject { build_stubbed(:role) }

it 'should be a valid with all the correct attributes' do
expect(subject).to be_valid
end

it 'should be invalid without name' do
subject.name = ''
expect(subject).to_not be_valid
end
end
end