annotate vendor/plugins/redmine_bibliography/app/controllers/publications_controller.rb @ 1051:ef882e222003 bibplugin_bibtex

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