Merge branch 'master' of https://github.com/openHPI/codeocean
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
class RequestForCommentsController < ApplicationController
|
class RequestForCommentsController < ApplicationController
|
||||||
before_action :set_request_for_comment, only: [:show, :edit, :update, :destroy]
|
before_action :set_request_for_comment, only: [:show, :edit, :update, :destroy, :mark_as_solved]
|
||||||
|
|
||||||
skip_after_action :verify_authorized
|
skip_after_action :verify_authorized
|
||||||
|
|
||||||
@ -20,6 +20,18 @@ class RequestForCommentsController < ApplicationController
|
|||||||
render 'index'
|
render 'index'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def mark_as_solved
|
||||||
|
authorize!
|
||||||
|
@request_for_comment.solved = true
|
||||||
|
respond_to do |format|
|
||||||
|
if @request_for_comment.save
|
||||||
|
format.json { render :show, status: :ok, location: @request_for_comment }
|
||||||
|
else
|
||||||
|
format.json { render json: @request_for_comment.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# GET /request_for_comments/1
|
# GET /request_for_comments/1
|
||||||
# GET /request_for_comments/1.json
|
# GET /request_for_comments/1.json
|
||||||
def show
|
def show
|
||||||
@ -70,6 +82,6 @@ class RequestForCommentsController < ApplicationController
|
|||||||
|
|
||||||
# Never trust parameters from the scary internet, only allow the white list through.
|
# Never trust parameters from the scary internet, only allow the white list through.
|
||||||
def request_for_comment_params
|
def request_for_comment_params
|
||||||
params.require(:request_for_comment).permit(:exercise_id, :file_id, :question, :requested_at).merge(user_id: current_user.id, user_type: current_user.class.name)
|
params.require(:request_for_comment).permit(:exercise_id, :file_id, :question, :requested_at, :solved).merge(user_id: current_user.id, user_type: current_user.class.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -35,6 +35,7 @@ module CodeOcean
|
|||||||
|
|
||||||
has_many :files
|
has_many :files
|
||||||
has_many :testruns
|
has_many :testruns
|
||||||
|
has_many :comments
|
||||||
alias_method :descendants, :files
|
alias_method :descendants, :files
|
||||||
|
|
||||||
mount_uploader :native_file, FileUploader
|
mount_uploader :native_file, FileUploader
|
||||||
|
@ -6,9 +6,11 @@ class ExternalUser < ActiveRecord::Base
|
|||||||
|
|
||||||
def displayname
|
def displayname
|
||||||
result = name
|
result = name
|
||||||
|
Rails.cache.fetch("#{cache_key}/displayname", expires_in: 12.hours) do
|
||||||
if(consumer.name == 'openHPI')
|
if(consumer.name == 'openHPI')
|
||||||
result = Xikolo::UserClient.get(external_id.to_s)[:display_name]
|
result = Xikolo::UserClient.get(external_id.to_s)[:display_name]
|
||||||
end
|
end
|
||||||
|
end
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
class RequestForComment < ActiveRecord::Base
|
class RequestForComment < ActiveRecord::Base
|
||||||
|
include Creation
|
||||||
belongs_to :exercise
|
belongs_to :exercise
|
||||||
belongs_to :file, class_name: 'CodeOcean::File'
|
belongs_to :file, class_name: 'CodeOcean::File'
|
||||||
belongs_to :user, polymorphic: true
|
|
||||||
|
|
||||||
before_create :set_requested_timestamp
|
before_create :set_requested_timestamp
|
||||||
|
|
||||||
@ -25,12 +25,16 @@ class RequestForComment < ActiveRecord::Base
|
|||||||
limit 1").first
|
limit 1").first
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def comments_count
|
||||||
|
submission.files.map { |file| file.comments.size}.sum
|
||||||
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
"RFC-" + self.id.to_s
|
"RFC-" + self.id.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def self.row_number_user_sql
|
def self.row_number_user_sql
|
||||||
select("id, user_id, exercise_id, file_id, question, requested_at, created_at, updated_at, user_type, row_number() OVER (PARTITION BY user_id ORDER BY created_at DESC) as row_number").to_sql
|
select("id, user_id, exercise_id, file_id, question, requested_at, created_at, updated_at, user_type, solved, row_number() OVER (PARTITION BY user_id ORDER BY created_at DESC) as row_number").to_sql
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
class RequestForCommentPolicy < ApplicationPolicy
|
class RequestForCommentPolicy < ApplicationPolicy
|
||||||
|
def author?
|
||||||
|
@user == @record.author
|
||||||
|
end
|
||||||
|
private :author?
|
||||||
|
|
||||||
def create?
|
def create?
|
||||||
everyone
|
everyone
|
||||||
@ -13,6 +16,10 @@ class RequestForCommentPolicy < ApplicationPolicy
|
|||||||
define_method(action) { admin? }
|
define_method(action) { admin? }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def mark_as_solved?
|
||||||
|
admin? || author?
|
||||||
|
end
|
||||||
|
|
||||||
def edit?
|
def edit?
|
||||||
admin?
|
admin?
|
||||||
end
|
end
|
||||||
|
@ -4,18 +4,28 @@ h1 = RequestForComment.model_name.human(count: 2)
|
|||||||
table.table.sortable
|
table.table.sortable
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
|
th
|
||||||
|
i class="fa fa-lightbulb-o" aria-hidden="true" title = t('request_for_comments.solved') align="right"
|
||||||
th = t('activerecord.attributes.request_for_comments.exercise')
|
th = t('activerecord.attributes.request_for_comments.exercise')
|
||||||
th = t('activerecord.attributes.request_for_comments.question')
|
th = t('activerecord.attributes.request_for_comments.question')
|
||||||
|
th
|
||||||
|
i class="fa fa-comment" aria-hidden="true" title = t('request_for_comments.comments') align="center"
|
||||||
th = t('activerecord.attributes.request_for_comments.username')
|
th = t('activerecord.attributes.request_for_comments.username')
|
||||||
th = t('activerecord.attributes.request_for_comments.requested_at')
|
th = t('activerecord.attributes.request_for_comments.requested_at')
|
||||||
tbody
|
tbody
|
||||||
- @request_for_comments.each do |request_for_comment|
|
- @request_for_comments.each do |request_for_comment|
|
||||||
tr data-id=request_for_comment.id
|
tr data-id=request_for_comment.id
|
||||||
|
- if request_for_comment.solved?
|
||||||
|
td
|
||||||
|
span class="fa fa-check" aria-hidden="true"
|
||||||
|
- else
|
||||||
|
td = ''
|
||||||
td = link_to(request_for_comment.exercise.title, request_for_comment)
|
td = link_to(request_for_comment.exercise.title, request_for_comment)
|
||||||
- if request_for_comment.has_attribute?(:question) && request_for_comment.question
|
- if request_for_comment.has_attribute?(:question) && request_for_comment.question
|
||||||
td = truncate(request_for_comment.question, length: 200)
|
td = truncate(request_for_comment.question, length: 200)
|
||||||
- else
|
- else
|
||||||
td = '-'
|
td = '-'
|
||||||
|
td = request_for_comment.comments_count
|
||||||
td = request_for_comment.user.displayname
|
td = request_for_comment.user.displayname
|
||||||
td = t('shared.time.before', time: distance_of_time_in_words_to_now(request_for_comment.requested_at))
|
td = t('shared.time.before', time: distance_of_time_in_words_to_now(request_for_comment.requested_at))
|
||||||
|
|
||||||
|
@ -14,13 +14,24 @@
|
|||||||
%>
|
%>
|
||||||
<%= user.displayname %> | <%= @request_for_comment.requested_at %>
|
<%= user.displayname %> | <%= @request_for_comment.requested_at %>
|
||||||
</p>
|
</p>
|
||||||
|
<h5>
|
||||||
|
<u><%= t('activerecord.attributes.exercise.instructions') %>:</u> "<%= @request_for_comment.exercise.description %>"
|
||||||
|
</h5>
|
||||||
|
|
||||||
<h5>
|
<h5>
|
||||||
<% if @request_for_comment.question and not @request_for_comment.question == '' %>
|
<% if @request_for_comment.question and not @request_for_comment.question == '' %>
|
||||||
<%= t('activerecord.attributes.request_for_comments.question')%>: "<%= @request_for_comment.question %>"
|
<u><%= t('activerecord.attributes.request_for_comments.question')%>:</u> "<%= @request_for_comment.question %>"
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= t('request_for_comments.no_question') %>
|
<u><%= t('activerecord.attributes.request_for_comments.question')%>:</u> <%= t('request_for_comments.no_question') %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</h5>
|
</h5>
|
||||||
|
<% if (policy(@request_for_comment).mark_as_solved? and not @request_for_comment.solved?) %>
|
||||||
|
<button class="btn btn-default" id="mark-as-solved-button"><%= t('request_for_comments.mark_as_solved') %></button>
|
||||||
|
<% elsif (@request_for_comment.solved?) %>
|
||||||
|
<button type="button" class="btn btn-success"><%= t('request_for_comments.solved') %></button>
|
||||||
|
<% else %>
|
||||||
|
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
@ -37,6 +48,22 @@ also, all settings from the rails model needed for the editor configuration in t
|
|||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var solvedButton = $('#mark-as-solved-button');
|
||||||
|
|
||||||
|
solvedButton.on('click', function(event){
|
||||||
|
var jqrequest = $.ajax({
|
||||||
|
dataType: 'json',
|
||||||
|
method: 'GET',
|
||||||
|
url: location + '/mark_as_solved'
|
||||||
|
});
|
||||||
|
|
||||||
|
jqrequest.done(function(response){
|
||||||
|
if(response.solved){
|
||||||
|
solvedButton.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// set file paths for ace
|
// set file paths for ace
|
||||||
var ACE_FILES_PATH = '/assets/ace/';
|
var ACE_FILES_PATH = '/assets/ace/';
|
||||||
_.each(['modePath', 'themePath', 'workerPath'], function(attribute) {
|
_.each(['modePath', 'themePath', 'workerPath'], function(attribute) {
|
||||||
|
@ -1 +1 @@
|
|||||||
json.extract! @request_for_comment, :id, :user_id, :exercise_id, :file_id, :requested_at, :created_at, :updated_at, :user_type
|
json.extract! @request_for_comment, :id, :user_id, :exercise_id, :file_id, :requested_at, :created_at, :updated_at, :user_type, :solved
|
||||||
|
@ -78,6 +78,7 @@ de:
|
|||||||
password_confirmation: Passwort-Bestätigung
|
password_confirmation: Passwort-Bestätigung
|
||||||
role: Rolle
|
role: Rolle
|
||||||
request_for_comments:
|
request_for_comments:
|
||||||
|
comments: Kommentare
|
||||||
exercise: Aufgabe
|
exercise: Aufgabe
|
||||||
execution_environment: Sprache
|
execution_environment: Sprache
|
||||||
username: Benutzername
|
username: Benutzername
|
||||||
@ -161,6 +162,7 @@ de:
|
|||||||
show:
|
show:
|
||||||
link: Konsument
|
link: Konsument
|
||||||
errors:
|
errors:
|
||||||
|
connection_refused: Verbindung abgelehnt
|
||||||
index:
|
index:
|
||||||
count: Anzahl
|
count: Anzahl
|
||||||
execution_environments:
|
execution_environments:
|
||||||
@ -350,10 +352,13 @@ de:
|
|||||||
body: 'Bitte besuchen Sie %{link}, sofern Sie Ihr Passwort zurücksetzen wollen.'
|
body: 'Bitte besuchen Sie %{link}, sofern Sie Ihr Passwort zurücksetzen wollen.'
|
||||||
subject: Anweisungen zum Zurücksetzen Ihres Passworts
|
subject: Anweisungen zum Zurücksetzen Ihres Passworts
|
||||||
request_for_comments:
|
request_for_comments:
|
||||||
|
comments: Kommentare
|
||||||
index:
|
index:
|
||||||
get_my_comment_requests: Meine Kommentaranfragen
|
get_my_comment_requests: Meine Kommentaranfragen
|
||||||
all: "Alle Kommentaranfragen"
|
all: "Alle Kommentaranfragen"
|
||||||
no_question: "Der Autor hat keine Frage zu dieser Anfrage gestellt."
|
no_question: "Der Autor hat keine Frage zu dieser Anfrage gestellt."
|
||||||
|
mark_as_solved: "Diese Frage als beantwortet markieren"
|
||||||
|
solved: "Diese Frage wurde erfolgreich beantwortet"
|
||||||
sessions:
|
sessions:
|
||||||
create:
|
create:
|
||||||
failure: Fehlerhafte E-Mail oder Passwort.
|
failure: Fehlerhafte E-Mail oder Passwort.
|
||||||
|
@ -78,6 +78,7 @@ en:
|
|||||||
password_confirmation: Passwort Confirmation
|
password_confirmation: Passwort Confirmation
|
||||||
role: Role
|
role: Role
|
||||||
request_for_comments:
|
request_for_comments:
|
||||||
|
comments: Comments
|
||||||
exercise: Exercise
|
exercise: Exercise
|
||||||
execution_environment: Language
|
execution_environment: Language
|
||||||
username: Username
|
username: Username
|
||||||
@ -161,6 +162,7 @@ en:
|
|||||||
show:
|
show:
|
||||||
link: Consumer
|
link: Consumer
|
||||||
errors:
|
errors:
|
||||||
|
connection_refused: Connection refused
|
||||||
index:
|
index:
|
||||||
count: Count
|
count: Count
|
||||||
execution_environments:
|
execution_environments:
|
||||||
@ -350,10 +352,13 @@ en:
|
|||||||
body: 'Please visit %{link} if you want to reset your password.'
|
body: 'Please visit %{link} if you want to reset your password.'
|
||||||
subject: Password reset instructions
|
subject: Password reset instructions
|
||||||
request_for_comments:
|
request_for_comments:
|
||||||
|
comments: Comments
|
||||||
index:
|
index:
|
||||||
all: All Requests for Comments
|
all: All Requests for Comments
|
||||||
get_my_comment_requests: My Requests for Comments
|
get_my_comment_requests: My Requests for Comments
|
||||||
no_question: "The author did not enter a question for this request."
|
no_question: "The author did not enter a question for this request."
|
||||||
|
mark_as_solved: "Mark this question as answered"
|
||||||
|
solved: "This question has been answered"
|
||||||
sessions:
|
sessions:
|
||||||
create:
|
create:
|
||||||
failure: Invalid email or password.
|
failure: Invalid email or password.
|
||||||
|
@ -2,13 +2,17 @@ FILENAME_REGEXP = /[\w\.]+/ unless Kernel.const_defined?(:FILENAME_REGEXP)
|
|||||||
|
|
||||||
Rails.application.routes.draw do
|
Rails.application.routes.draw do
|
||||||
resources :code_harbor_links
|
resources :code_harbor_links
|
||||||
resources :request_for_comments
|
resources :request_for_comments do
|
||||||
get '/my_request_for_comments', as: 'my_request_for_comments', to: 'request_for_comments#get_my_comment_requests'
|
member do
|
||||||
|
get :mark_as_solved
|
||||||
|
end
|
||||||
|
end
|
||||||
resources :comments, except: [:destroy] do
|
resources :comments, except: [:destroy] do
|
||||||
collection do
|
collection do
|
||||||
delete :destroy
|
delete :destroy
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
get '/my_request_for_comments', as: 'my_request_for_comments', to: 'request_for_comments#get_my_comment_requests'
|
||||||
|
|
||||||
delete '/comment_by_id', to: 'comments#destroy_by_id'
|
delete '/comment_by_id', to: 'comments#destroy_by_id'
|
||||||
put '/comments', to: 'comments#update'
|
put '/comments', to: 'comments#update'
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
class AddSolvedToRequestForComments < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :request_for_comments, :solved, :boolean
|
||||||
|
end
|
||||||
|
end
|
@ -11,7 +11,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 20160512131539) do
|
ActiveRecord::Schema.define(version: 20160624130951) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
@ -190,6 +190,7 @@ ActiveRecord::Schema.define(version: 20160512131539) do
|
|||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.string "user_type"
|
t.string "user_type"
|
||||||
t.text "question"
|
t.text "question"
|
||||||
|
t.boolean "solved"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "submissions", force: true do |t|
|
create_table "submissions", force: true do |t|
|
||||||
|
Reference in New Issue
Block a user