<commit_before>require 'grape'

module Api
  class TaskComments < Grape::API
    helpers AuthenticationHelpers
    helpers AuthorisationHelpers

    before do
      authenticated?
    end

    desc 'Add a new comment to a task'
    params do
      requires :type, type: Symbol, default: :text, values: [:text, :image, :audio, :video], desc: 'The type of comment to add to the task'
      optional :comment, type: String, desc: 'The comment text to add to the task'
      optional :attachment, type: Rack::Multipart::UploadedFile, desc: 'Image, sound, or video comment file'
    end
    post '/projects/:project_id/task_def_id/:task_definition_id/comments' do
      project = Project.find(params[:project_id])
      task_definition = project.unit.task_definitions.find(params[:task_definition_id])

      unless authorise? current_user, project, :make_submission
        error!({ error: 'Not authorised to create a comment for this task' }, 403)
      end
      
      content_type = params[:type]      
      text_comment = params[:comment]
      attachment_comment = params[:attachment]    

      task = project.task_for_task_definition(task_definition)
      type_string = content_type.to_s

      if content_type == :text
        if text_comment.nil?
          error!({ error: "text field is empty"}, 403)          
        end
        result = task.add_text_comment(current_user, text_comment, content_type)
      else
        if attachment_comment.nil?
          error!({ error: "No file attached"}, 403)          
        else
          unless FileHelper.accept_file(attachment_comment, "comment attachment - TaskComment", type_string)
            error!({ error: "File attached is not a valid #{type_string} file" }, 403)
          end
        end
        result = task.add_comment_with_attachment(current_user, attachment_comment, content_type)
      end
      
      if result.nil?
        error!({ error: 'No comment added. Comment duplicates last comment, so ignored.' }, 403)
      else
        result.mark_as_read(current_user, project.unit)
        result
      end
    end
    
    desc 'Get an attachment related to a task comment'
    params do
      optional :as_attachment, type: Boolean, desc: 'Whether or not to download file as attachment. Default is false.'
    end
    get '/projects/:project_id/task_def_id/:task_definition_id/comments/:id' do
      project = Project.find(params[:project_id])
      task_definition = project.unit.task_definitions.find(params[:task_definition_id])

      unless authorise? current_user, project, :get
        error!({ error: 'You cannot read the comments for this task' }, 403)
      end

      if project.has_task_for_task_definition? task_definition
        task = project.task_for_task_definition(task_definition)

        comment = task.comments.find(params[:id])

        content_type comment.attachment.content_type
        env['api.format'] = :binary
        if params[:as_attachment]
          header['Content-Disposition'] = "attachment; filename=#{comment.attachment_file_name}"
        end
        File.read(comment.attachment.path)
      end
    end

    desc 'Get the comments related to a task'
    get '/projects/:project_id/task_def_id/:task_definition_id/comments' do
      project = Project.find(params[:project_id])
      task_definition = project.unit.task_definitions.find(params[:task_definition_id])

      unless authorise? current_user, project, :get
        error!({ error: 'You cannot read the comments for this task' }, 403)
      end

      if project.has_task_for_task_definition? task_definition
        task = project.task_for_task_definition(task_definition)

        comments = task.all_comments.order('created_at ASC')
        result = comments.map do |c|
          {
            id: c.id,
            comment: c.comment,
            has_attachment: c.attachment.exists?,
            type: c.content_type,
            is_new: c.new_for?(current_user),
            author: {
              id: c.user.id,
              name: c.user.name,
              email: c.user.email
            },
            recipient: {
              id: c.recipient.id,
              name: c.recipient.name,
              email: c.user.email
            },
            created_at: c.created_at,
            recipient_read_time: c.time_read_by(c.recipient),
          }
        end
        task.mark_comments_as_read(current_user, comments)
      else
        result = []
      end
      result
    end

    desc 'Delete a comment'
    delete '/projects/:project_id/task_def_id/:task_definition_id/comments/:id' do
      project = Project.find(params[:project_id])
      task_definition = project.unit.task_definitions.find(params[:task_definition_id])
<commit_msg>FIX: Comment Serialize<commit_after>require 'grape'

module Api
  class TaskComments < Grape::API
    helpers AuthenticationHelpers
    helpers AuthorisationHelpers

    before do
      authenticated?
    end

    desc 'Add a new comment to a task'
    params do
      requires :type, type: Symbol, default: :text, values: [:text, :image, :audio, :video], desc: 'The type of comment to add to the task'
      optional :comment, type: String, desc: 'The comment text to add to the task'
      optional :attachment, type: Rack::Multipart::UploadedFile, desc: 'Image, sound, or video comment file'
    end
    post '/projects/:project_id/task_def_id/:task_definition_id/comments' do
      project = Project.find(params[:project_id])
      task_definition = project.unit.task_definitions.find(params[:task_definition_id])

      unless authorise? current_user, project, :make_submission
        error!({ error: 'Not authorised to create a comment for this task' }, 403)
      end
      
      content_type = params[:type]      
      text_comment = params[:comment]
      attachment_comment = params[:attachment]    

      task = project.task_for_task_definition(task_definition)
      type_string = content_type.to_s

      if content_type == :text
        if text_comment.nil?
          error!({ error: "text field is empty"}, 403)          
        end
        result = task.add_text_comment(current_user, text_comment, content_type)
      else
        if attachment_comment.nil?
          error!({ error: "No file attached"}, 403)          
        else
          unless FileHelper.accept_file(attachment_comment, "comment attachment - TaskComment", type_string)
            error!({ error: "File attached is not a valid #{type_string} file" }, 403)
          end
        end
        result = task.add_comment_with_attachment(current_user, attachment_comment, content_type)
      end
      
      if result.nil?
        error!({ error: 'No comment added. Comment duplicates last comment, so ignored.' }, 403)
      else
        result.mark_as_read(current_user, project.unit)
        result.serialize(current_user)
      end
    end
    
    desc 'Get an attachment related to a task comment'
    params do
      optional :as_attachment, type: Boolean, desc: 'Whether or not to download file as attachment. Default is false.'
    end
    get '/projects/:project_id/task_def_id/:task_definition_id/comments/:id' do
      project = Project.find(params[:project_id])
      task_definition = project.unit.task_definitions.find(params[:task_definition_id])

      unless authorise? current_user, project, :get
        error!({ error: 'You cannot read the comments for this task' }, 403)
      end

      if project.has_task_for_task_definition? task_definition
        task = project.task_for_task_definition(task_definition)

        comment = task.comments.find(params[:id])

        content_type comment.attachment.content_type
        env['api.format'] = :binary
        if params[:as_attachment]
          header['Content-Disposition'] = "attachment; filename=#{comment.attachment_file_name}"
        end
        File.read(comment.attachment.path)
      end
    end

    desc 'Get the comments related to a task'
    get '/projects/:project_id/task_def_id/:task_definition_id/comments' do
      project = Project.find(params[:project_id])
      task_definition = project.unit.task_definitions.find(params[:task_definition_id])

      unless authorise? current_user, project, :get
        error!({ error: 'You cannot read the comments for this task' }, 403)
      end

      if project.has_task_for_task_definition? task_definition
        task = project.task_for_task_definition(task_definition)

        comments = task.all_comments.order('created_at ASC')
        result = comments.map { |c| c.serialize(current_user) }          
        task.mark_comments_as_read(current_user, comments)
      else
        result = []
      end
      result
    end

    desc 'Delete a comment'
    delete '/projects/:project_id/task_def_id/:task_definition_id/comments/:id' do
      project = Project.find(params[:project_id])
      task_definition = project.unit.task_definitions.find(params[:task_definition_id])

{'fraction_non_alphanumeric': 0.09130580731789191, 'fraction_numerical': 0.004699563611950319, 'mean_word_length': 2.7475890985324947, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3591465', 'n_tokens_mistral': 2565, 'n_tokens_neox': 2506, 'n_words': 657}