annotate vendor/plugins/redmine_bibliography/app/controllers/publications_controller.rb @ 951:010291c90b0b bibplugin_bibtex

Fixes a bug with the authors div - it was being replicated for each author; added a fieldset in order to better handle each author; simulates a click for each author in the parsing of the bibtex file.
author luisf <luis.figueira@eecs.qmul.ac.uk>
date Fri, 03 Aug 2012 18:33:08 +0100
parents be4106d14a35
children ef882e222003
rev   line source
luisf@613 1 # -*- coding: utf-8 -*-
luis@385 2 # vendor/plugins/redmine_bibliography/app/controllers/publications_controller.rb
luis@385 3
luis@947 4 class BibtexParsingError < Exception; end
luis@947 5
luis@328 6 class PublicationsController < ApplicationController
luis@425 7 unloadable
luis@946 8
luis@560 9 model_object Publication
luis@947 10 before_filter :find_model_object, :except => [:parse_bibtex, :new, :create, :index, :get_bibtex_required_fields, :autocomplete_for_project, :add_author, :sort_author_order, :autocomplete_for_author, :get_user_info ]
luis@631 11 before_filter :find_project_by_project_id, :authorize, :only => [ :edit, :new, :update, :create ]
luis@946 12
luis@404 13 def new
luis@539 14 find_project_by_project_id
luis@539 15 @publication = Publication.new
luis@946 16
luis@445 17 # we'll always want a new publication to have its bibtex entry
luis@539 18 @publication.build_bibtex_entry
luis@946 19
luis@446 20 # and at least one author
luis@608 21 # @publication.authorships.build.build_author
chris@647 22 @author_options = [["#{User.current.name} (@#{User.current.mail.partition('@')[2]})", "#{User.current.class.to_s}_#{User.current.id.to_s}"]]
luis@947 23 end
luis@614 24
luis@614 25
luis@947 26 def parse_bibtex
luis@947 27 find_project_by_project_id
luis@947 28
luis@947 29 @bibtex_paste = params[:bibtex_paste]
luis@947 30
luis@947 31 begin
luis@947 32 bib = BibTeX.parse(@bibtex_paste)
luis@947 33
luis@947 34 if bib.errors.present? or bib[0].class == NilClass
luis@947 35 raise BibtexParsingError, "Bibtex Parsing Error"
luis@947 36 end
luis@947 37
luis@947 38 respond_to do |format|
luis@947 39 format.js {
luis@947 40 render(:update) {|page|
luis@947 41 flash[:notice] = "Correctly parsed BibTeX entry"
luis@947 42
luis@947 43 bibtex_entry_no = BibtexEntryType.find_by_name(bib[0].type.to_s).id
luis@947 44 page["publication_title"].value = bib[0][:title]
luis@947 45 page["publication_bibtex_entry_attributes_entry_type"].value = bibtex_entry_no
luis@951 46
luis@947 47 BibtexEntryType.fields(bibtex_entry_no).each do |field|
luis@947 48 page["publication_bibtex_entry_attributes_#{field}"].value = bib[0][field]
luis@947 49 end
luis@951 50
luis@951 51 # for each author simulates a click and fills the author info
luis@951 52 bib[0].authors.each do |author|
luis@951 53 page["add_another_author"].click
luis@951 54 # page.alert(bib[0].authors.length)
luis@951 55 # page.alert(page["authors"].first.id)
luis@951 56
luis@951 57 end
luis@951 58
luis@951 59
luis@951 60
luis@947 61 }
luis@947 62 }
luis@947 63 end
luis@947 64
luis@947 65 rescue BibtexParsingError => e
luis@947 66 logger.error { "Bibtex Parsing Error #{bib.errors}" }
luis@947 67
luis@947 68 # todo: not showing... should be inside render?
luis@947 69 flash[:error] = e.message
luis@947 70
luis@947 71 respond_to do |format|
luis@947 72 format.js{
luis@947 73 render(:update) {|page|
luis@947 74 }
luis@947 75 }
luis@947 76 end
luis@947 77
luis@947 78 end
luis@947 79
luis@519 80 end
luis@409 81
luis@947 82
luis@947 83 def create
luisf@613 84 @project = Project.find(params[:project_id])
luisf@613 85
chris@661 86 @author_options = []
luis@614 87
luis@390 88 @publication = Publication.new(params[:publication])
luis@553 89 @publication.projects << @project unless @project.nil?
luis@946 90
luis@448 91 if @publication.save
luis@666 92 @publication.notify_authors_publication_added(@project)
luis@946 93
luis@445 94 flash[:notice] = "Successfully created publication."
luisf@613 95 redirect_to :action => :show, :id => @publication, :project_id => @project
luis@445 96 else
luisf@613 97 render :action => 'new', :project_id => @project
luis@445 98 end
luis@445 99 end
luis@445 100
luis@445 101 def index
luis@538 102 if !params[:project_id].nil?
luis@538 103 find_project_by_project_id
luis@538 104 @project = Project.find(params[:project_id])
luis@538 105 @publications = Publication.find :all, :joins => :projects, :conditions => ["project_id = ?", @project.id]
luis@538 106 else
luis@538 107 @publications = Publication.find :all
luis@538 108 end
luis@445 109 end
luis@445 110
luis@445 111 def new_from_bibfile
luis@391 112 @publication.current_step = session[:publication_step]
luis@946 113
luis@404 114 # contents of the paste text area
luis@404 115 bibtex_entry = params[:bibtex_entry]
luis@384 116
luis@404 117 # method for creating "pasted" bibtex entries
luis@424 118 if bibtex_entry
luis@409 119 parse_bibtex_list bibtex_entry
luis@404 120 end
luis@329 121 end
luis@329 122
luis@675 123 def get_bibtex_required_fields
luis@675 124
luis@947 125 fields = BibtexEntryType.fields(params[:q])
luis@675 126
luis@675 127 respond_to do |format|
luis@675 128 format.js {
luis@699 129 render(:update) {|page|
luis@947 130 if params[:q].empty?
luis@699 131 page << "hideOnLoad();"
luis@699 132 else
luis@699 133 page << "show_required_bibtex_fields(#{fields.to_json()});"
luis@675 134 end
luis@675 135 }
luis@675 136 }
luis@946 137
luis@675 138 end
luis@675 139 end
luis@675 140
luis@467 141 def add_author
luis@467 142 if (request.xhr?)
luis@467 143 render :text => User.find(params[:user_id]).name
luis@467 144 else
luis@467 145 # No? Then render an action.
luis@467 146 #render :action => 'view_attribute', :attr => @name
luis@675 147 logger.error { "Error while adding Author to publication." }
luis@467 148 end
luis@467 149 end
luis@467 150
luis@547 151 def edit
luis@547 152 find_project_by_project_id unless params[:project_id].nil?
luis@946 153
luis@609 154 @edit_view = true;
luis@428 155 @publication = Publication.find(params[:id])
luis@626 156 @selected_bibtex_entry_type_id = @publication.bibtex_entry.entry_type
luis@626 157
chris@647 158 @author_options = []
luis@946 159
luis@685 160 @bibtype_fields = BibtexEntryType.fields(@selected_bibtex_entry_type_id)
luis@430 161 end
luis@430 162
luis@445 163 def update
luis@448 164 @publication = Publication.find(params[:id])
luis@538 165
chris@661 166 @author_options = []
luis@626 167
luis@430 168 if @publication.update_attributes(params[:publication])
luis@947 169 flash[:notice] = "Successfully Updated Publication."
luis@538 170
luis@538 171 if !params[:project_id].nil?
luis@538 172 redirect_to :action => :show, :id => @publication, :project_id => params[:project_id]
luis@538 173 else
luis@538 174 redirect_to :action => :show, :id => @publication
luis@538 175 end
luis@430 176 else
luis@448 177 render :action => 'edit'
luis@448 178 end
luis@328 179 end
luis@328 180
luis@946 181
luis@425 182 def show
luis@535 183 find_project_by_project_id unless params[:project_id].nil?
luis@946 184
luis@425 185 if @publication.nil?
luis@579 186 @publications = Publication.all
luis@579 187 render "index", :alert => 'The publication was not found!'
luis@425 188 else
luis@425 189 @authors = @publication.authors
luis@425 190 @bibtext_entry = @publication.bibtex_entry
luis@425 191 end
luis@329 192 end
luis@329 193
luis@406 194 # parse string with bibtex authors
luis@406 195 def parse_authors(authors_entry)
luis@406 196 # in bibtex the authors are always seperated by "and"
luis@407 197 return authors_entry.split(" and ")
luis@406 198 end
luis@406 199
luis@406 200 # parses a list of bibtex
luis@406 201 def parse_bibtex_list(bibtex_list)
luis@406 202 bibliography = BibTeX.parse bibtex_list
luis@406 203
luis@406 204 no_entries = bibliography.data.length
luis@406 205
luis@406 206 # parses the bibtex entries
luis@406 207 bibliography.data.map do |d|
luis@407 208
luis@407 209 if d.class == BibTeX::Entry
luis@407 210 create_bibtex_entry d
luis@407 211 end
luis@406 212 end
luis@407 213 end
luis@407 214
luis@409 215 def create_bibtex_entry(d)
luis@407 216 @publication = Publication.new
luis@407 217 @bentry = BibtexEntry.new
luis@407 218 authors = []
luis@407 219 institution = ""
luis@407 220 email = ""
luis@409 221
luis@407 222 d.fields.keys.map do |field|
luis@407 223 case field.to_s
luis@407 224 when "author"
luis@407 225 authors = parse_authors d[field]
luis@407 226 when "title"
luis@407 227 @publication.title = d[field]
luis@407 228 when "institution"
luis@407 229 institution = d[field]
luis@407 230 when "email"
luis@407 231 email = d[field]
luis@407 232 else
luis@407 233 @bentry[field] = d[field]
luis@407 234 end
luis@407 235 end
luis@406 236
luis@406 237 @publication.bibtex_entry = @bentry
luis@407 238 @publication.save
luis@409 239
luis@424 240 # what is this for???
luis@424 241 # @created_publications << @publication.id
luis@409 242
luis@407 243 # need to save all authors
luis@407 244 # and establish the author-publication association
luis@407 245 # via the authorships table
luis@407 246 authors.each_with_index.map do |authorname, idx|
luis@407 247 author = Author.new(:name => authorname)
luis@407 248 if author.save!
luis@946 249 # todo: catch the errors...
luis@407 250 puts "SAVED"
luis@407 251 else
luis@407 252 puts "NOT SAVED"
luis@406 253 end
luis@406 254
luis@407 255 author.authorships.create!(
luis@946 256 :publication => @publication,
luis@946 257 :institution => institution,
luis@946 258 :email => email,
luis@946 259 :order => idx)
luis@407 260 end
luis@407 261 end
luis@409 262
luis@407 263 # parses the bibtex file
luis@407 264 def parse_bibtex_file
luis@407 265
luis@406 266 end
luis@406 267
luis@444 268 def import
luis@444 269 @publication = Publication.new
luis@946 270
luis@946 271
luis@444 272 end
luis@946 273
luis@461 274 def autocomplete_for_project
luis@461 275 @publication = Publication.find(params[:id])
luis@946 276
luis@464 277 @projects = Project.active.like(params[:q]).find(:all, :limit => 100) - @publication.projects
luis@461 278 logger.debug "Query for \"#{params[:q]}\" returned \"#{@projects.size}\" results"
luis@461 279 render :layout => false
luis@409 280 end
luis@947 281
luis@471 282
luis@601 283 def autocomplete_for_author
luis@519 284 @results = []
luis@946 285
luis@596 286 object_id = params[:object_id]
luis@598 287 @object_name = "publications[authorships_attributes][#{object_id}][search_results]"
luis@946 288
Chris@674 289 # cc 20110909 -- revert to like instead of like_unique -- see #289
Chris@674 290 authorships_list = Authorship.like(params[:q]).find(:all, :limit => 100)
luis@480 291 users_list = User.active.like(params[:q]).find(:all, :limit => 100)
luis@480 292
luis@591 293 logger.debug "Query for \"#{params[:q]}\" returned \"#{authorships_list.size}\" authorships and \"#{users_list.size}\" users"
luis@946 294
luis@601 295 @results = users_list
luis@601 296
luis@601 297 # TODO: can be optimized…
luis@601 298 authorships_list.each do |authorship|
luis@601 299 flag = true
luis@946 300
luis@601 301 users_list.each do |user|
luis@601 302 if authorship.name == user.name && authorship.email == user.mail && authorship.institution == user.institution
luis@601 303 Rails.logger.debug { "Rejecting Authorship #{authorship.id}" }
luis@601 304 flag = false
luis@601 305 break
luis@601 306 end
luis@601 307 end
luis@601 308
luis@601 309 @results << authorship if flag
luis@592 310 end
luis@592 311
luis@598 312 render :layout => false
luis@598 313 end
luis@946 314
luis@598 315 def get_user_info
luis@598 316 object_id = params[:object_id]
luis@598 317 value = params[:value]
luis@598 318 classname = Kernel.const_get(value.split('_')[0])
luis@592 319
luis@598 320 item = classname.find(value.split('_')[1])
luis@598 321
luis@598 322 name_field = "publication_authorships_attributes_#{object_id}_name_on_paper".to_sym
luis@598 323 email_field = "publication_authorships_attributes_#{object_id}_email".to_sym
luis@600 324 institution_field = "publication_authorships_attributes_#{object_id}_institution".to_sym
luis@946 325
luis@600 326 yes_radio = "publication_authorships_attributes_#{object_id}_identify_author_yes".to_sym
luis@946 327
luis@598 328 respond_to do |format|
luis@675 329 format.js {
luis@598 330 render(:update) {|page|
luis@598 331 page[name_field].value = item.name
luis@598 332 page[email_field].value = item.mail
luis@600 333 page[institution_field].value = item.institution
luis@600 334
luis@600 335 page[yes_radio].checked = true
luis@601 336 page[name_field].readOnly = true
luis@601 337 page[email_field].readOnly = true
luis@601 338 page[institution_field].readOnly = true
luis@598 339 }
luis@598 340 }
luis@598 341 end
luis@477 342 end
luis@471 343
luis@557 344 def sort_author_order
luis@557 345 params[:authorships].each_with_index do |id, index|
luis@557 346 Authorship.update_all(['auth_order=?', index+1], ['id=?', id])
luis@471 347 end
luis@471 348 render :nothing => true
luis@471 349 end
luis@574 350
luis@574 351 def add_project
luis@574 352 @projects = Project.find(params[:publication][:project_ids])
luis@574 353 @publication.projects << @projects
luis@579 354 @project = Project.find(params[:project_id])
luis@946 355
luis@574 356 # TODO luisf should also respond to HTML???
luis@574 357 respond_to do |format|
luis@574 358 format.html { redirect_to :back }
luis@574 359 format.js {
luis@574 360 render(:update) {|page|
luis@574 361 page[:add_project_form].reset
luis@574 362 page.replace_html :list_projects, :partial => 'list_projects'
luis@574 363 }
luis@574 364 }
luis@574 365 end
luis@574 366 end
luis@946 367
luis@946 368
luis@574 369 def remove_project
luis@579 370 @project = Project.find(params[:project_id])
luis@579 371 proj = Project.find(params[:remove_project_id])
luis@554 372
luis@574 373 if @publication.projects.length > 1
luis@579 374 if @publication.projects.exists? proj
luis@579 375 @publication.projects.delete proj if request.post?
luis@554 376 end
luis@554 377 else
luis@579 378 logger.error { "Cannot remove project from publication list" }
luis@554 379 end
luis@946 380
luis@591 381 logger.error { "CURRENT project name#{proj.name} and wanna delete #{@project.name}" }
luis@946 382
luis@579 383 render(:update) {|page|
luis@579 384 page.replace_html "list_projects", :partial => 'list_projects', :id => @publication
luis@579 385 }
luis@554 386 end
luis@946 387
luis@560 388 def destroy
luis@560 389 find_project_by_project_id
luis@946 390
luis@560 391 @publication.destroy
luis@946 392
luis@560 393 flash[:notice] = "Successfully deleted Publication."
luis@560 394 redirect_to :controller => :publications, :action => 'index', :project_id => @project
luis@560 395 end
luis@471 396
luis@538 397 private
luis@478 398
luis@328 399 end