Browse Source

Add lectures controller

Frans Bergman 7 years ago
parent
commit
e6d87d0a09

+ 3 - 0
app/assets/javascripts/lectures.coffee

@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/

+ 3 - 0
app/assets/stylesheets/lectures.scss

@@ -0,0 +1,3 @@
+// Place all the styles related to the lectures controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/

+ 55 - 0
app/controllers/lectures_controller.rb

@@ -0,0 +1,55 @@
+class LecturesController < ApplicationController
+  before_action :set_lecture, only: %i[show edit update destroy]
+  before_action :check_can_edit, only: %i[edit update]
+  before_action :check_can_create, only: %i[create]
+
+  def show; end
+
+  def new
+    @lecture = Lecture.new
+  end
+
+  def edit; end
+
+  def create
+    @lecture = Lecture.new(lecture_params)
+    if @lecture.save
+      flash[:success] = 'Created lecture'
+      redirect_to @lecture
+    else
+      render :new
+    end
+  end
+
+  def update
+    if @lecture.update(lecture_params)
+      flash[:success] = 'Updated lecture'
+      redirect_to @lecture
+    else
+      render :edit
+    end
+  end
+
+  private
+
+  # Use callbacks to share common setup or constraints between actions.
+  def set_lecture
+    @lecture = Lecture.find(params[:id])
+  end
+
+  def lecture_params
+    allowed = [:description]
+
+    allowed += %i[course_id starts_at ends_at location] if helpers.can_edit_full?
+
+    params.require(:lecture).permit(*allowed)
+  end
+
+  def check_can_create
+    redirect_to root_url unless helpers.can_edit_full?
+  end
+
+  def check_can_edit
+    redirect_to root_url unless helpers.can_edit_description?
+  end
+end

+ 15 - 0
app/helpers/lectures_helper.rb

@@ -0,0 +1,15 @@
+module LecturesHelper
+  def can_edit_description?
+    @lecture.course.users.merge(CourseParticipation.teachers).include?(current_user) || can_edit_full?
+  end
+
+  def can_edit_full?
+    begin
+      school = (@lecture && @lecture.course) ? @lecture.course.school : Course.find(params.require(:lecture)[:course_id]).school
+    rescue
+      return true
+    end
+
+    current_user.is_administrator_at?(school) || current_user.admin?
+  end
+end

+ 22 - 0
app/views/courses/show.html.erb

@@ -8,5 +8,27 @@
   <div class="col-md-6">
     <%= render partial: 'participants_panel', locals: { users: @course.users.merge(CourseParticipation.teachers), role: :teacher } %>
     <%= render partial: 'participants_panel', locals: { users: @course.users.merge(CourseParticipation.students), role: :student } %>
+    <div class="panel panel-default">
+      <div class="panel-heading">
+        Lectures
+      </div>
+      <table class="panel-body table table-striped table-bordered table-hover">
+        <tbody>
+          <% for lecture in @course.lectures do %>
+            <tr>
+              <td>
+                <%= link_to lecture.starts_at, lecture %>
+              </td>
+              <td>
+                <%= lecture.location %>
+              </td>
+              <td>
+                <%= truncate(lecture.description, length: 70) %>
+              </td>
+            </tr>
+          <% end %>
+        </tbody>
+      </table>
+    </div>
   </div>
 </div>

+ 18 - 0
app/views/lectures/_form.html.erb

@@ -0,0 +1,18 @@
+<%= bootstrap_form_for(@lecture) do |f| %>
+  <%= render 'shared/error_messages', object: f.object %>
+
+  <% if can_edit_full? %>
+    <%= f.select :course_id, options_for_select(current_user.schools_administering.map{ |school| school.courses }.flatten.map{ |course| [course.name, course.id] }) %>
+  <% else %>
+    <%= f.text_field :course, value: @lecture.course.name, disabled: true %>
+  <% end %>
+
+  <%= f.datetime_field :starts_at, disabled: !can_edit_full? %>
+  <%= f.datetime_field :ends_at, disabled: !can_edit_full? %>
+
+  <%= f.text_field :location, disabled: !can_edit_full? %>
+
+  <%= f.text_area :description %>
+
+  <%= f.submit yield(:button_text), class: "btn btn-primary" %>
+<% end %>

+ 9 - 0
app/views/lectures/edit.html.erb

@@ -0,0 +1,9 @@
+<% provide(:title, "Edit #{@lecture.course.name} lecture") %>
+<% provide(:button_text, 'Save changes') %>
+
+<h1>Update course</h1>
+<div class="row">
+  <div class="col-md-12">
+    <%= render 'form' %>
+  </div>
+</div>

+ 9 - 0
app/views/lectures/new.html.erb

@@ -0,0 +1,9 @@
+<% provide(:title, 'New Lecture') %>
+<% provide(:button_text, 'Create') %>
+
+<h1>Create new lecture</h1>
+<div class="row">
+  <div class="col-md-12">
+    <%= render 'form' %>
+  </div>
+</div>

+ 29 - 0
app/views/lectures/show.html.erb

@@ -0,0 +1,29 @@
+<% provide(:title, "#{@lecture.course.name} lecture") %>
+<div class="row">
+  <div class="col-md-12">
+    <h1><%= @lecture.course.name %> lecture</h1>
+  </div>
+</div>
+<div class="row">
+  <div class="col-md-6">
+    <ul>
+      <li>
+        Course: <%= link_to @lecture.course.name, course_path(@lecture.course) %>
+      </li>
+      <li>
+        Time: <%= @lecture.starts_at %> to <%= @lecture.ends_at %>
+      </li>
+      <li>
+        Location: <%= @lecture.location %>
+      </li>
+    </ul>
+    <p>
+      <%= format_content(@lecture.description) %>
+    </p>
+    <% if can_edit_description? %>
+      <%= link_to edit_lecture_path(@lecture), class: "btn btn-primary" do %>
+        <%= fa_icon "edit", text: "Edit" %>
+      <% end %>
+    <% end %>
+  </div>
+</div>

+ 1 - 0
config/routes.rb

@@ -19,4 +19,5 @@ Rails.application.routes.draw do
   resources :schools
   resources :courses
   resources :course_participations
+  resources :lectures
 end

+ 76 - 0
test/controllers/lectures_controller_test.rb

@@ -0,0 +1,76 @@
+require 'test_helper'
+
+class LecturesControllerTest < ActionDispatch::IntegrationTest
+  def setup
+    @lecture = lectures(:two)
+    @course = courses(:two)
+    @student_user = users(:billy)
+    @teacher_user = users(:ben)
+    @school_admin = users(:daniel)
+    @global_admin = users(:admin)
+  end
+
+  test "should show lecture" do
+    log_in_as @student_user
+    get lecture_path @lecture
+    assert_response :success
+  end
+
+  test "student should not edit lecture" do
+    log_in_as @student_user
+    get edit_lecture_path @lecture
+    assert_redirected_to root_url
+  end
+
+  test "teacher should edit and update lecture" do
+    log_in_as @teacher_user
+    get edit_lecture_path @lecture
+    assert_response :success
+    patch lecture_path(@lecture), params: { lecture: { description: "New Lorem Ipsum" } }
+    assert_redirected_to @lecture
+    assert_equal "New Lorem Ipsum", @lecture.reload.description
+  end
+
+  test "school admin should create new lecture" do
+    log_in_as @school_admin
+    get new_lecture_path
+    assert_response :success
+    assert_difference "Lecture.count", 1 do
+      post lectures_path, params: { lecture: { description: "Lorem Ipsum",
+                                             location: "1A",
+                                             course_id: @course.id,
+                                             starts_at: 2.days.ago,
+                                             ends_at: 2.days.since } }
+    end
+  end
+
+  test "global admin should create new lecture" do
+    log_in_as @global_admin
+    get new_lecture_path
+    assert_response :success
+    assert_difference "Lecture.count", 1 do
+      post lectures_path, params: { lecture: { description: "New Lecture",
+                                             location: "1A",
+                                             course_id: @course.id,
+                                             starts_at: 2.days.ago,
+                                             ends_at: 2.days.since } }
+    end
+  end
+
+  test "unauthorized should not create lecture" do
+    log_in_as @student_user
+    assert_no_difference "Lecture.count" do
+      # With valid course id
+      post lectures_path, params: { lecture: { description: "New Lecture",
+                                             location: "1A",
+                                             course_id: @course.id,
+                                             starts_at: 2.days.ago,
+                                             ends_at: 2.days.since } }
+      # Without course id
+      post lectures_path, params: { lecture: { description: "New Lecture",
+                                             location: "1A",
+                                             starts_at: 2.days.ago,
+                                             ends_at: 2.days.since } }
+    end
+  end
+end

+ 10 - 0
test/fixtures/course_participations.yml

@@ -9,3 +9,13 @@ two:
   course: one
   user: billy
   role: student
+
+three:
+  course: two
+  user: daniel
+  role: teacher
+
+four:
+  course: two
+  user: ben
+  role: teacher