luisf@613: # -*- coding: utf-8 -*- luis@385: # vendor/plugins/redmine_bibliography/app/controllers/publications_controller.rb luis@385: luis@947: class BibtexParsingError < Exception; end luis@947: luis@328: class PublicationsController < ApplicationController luis@425: unloadable luis@946: luis@560: model_object Publication luis@1051: 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: before_filter :find_project_by_project_id, :authorize, :only => [ :edit, :new, :update, :create ] luis@946: luis@404: def new luis@539: find_project_by_project_id luis@539: @publication = Publication.new luis@946: luis@445: # we'll always want a new publication to have its bibtex entry luis@539: @publication.build_bibtex_entry luis@946: luis@446: # and at least one author luis@1051: # @publication.authorships.build.build_author chris@647: @author_options = [["#{User.current.name} (@#{User.current.mail.partition('@')[2]})", "#{User.current.class.to_s}_#{User.current.id.to_s}"]] luis@947: end luis@614: luis@947: def parse_bibtex luis@947: find_project_by_project_id luis@947: luis@1051: bibtex_paste = params[:bibtex_paste] luis@1051: bib = BibTeX.parse(bibtex_paste) luis@947: luis@1051: respond_to do |format| luis@1051: if bib.errors.present? or bib[0].class == NilClass luis@947: luis@1051: # todo: response for HTML luis@1051: format.html{} luis@1051: luis@1051: # todo: better error handling luis@1051: biberror = bib.errors[0].trace[4] luis@1051: logger.error { "BibTex Parsing Error: #{biberror}" } luis@1051: flash[:error] = "BibTex Parsing Error: #{biberror}" luis@1051: #raise BibtexParsingError, "Bibtex Parsing Error: biberror}" luis@1051: format.js luis@1051: else luis@1051: @ieee_prev = CiteProc.process bib.to_citeproc, :style => :ieee, :format => :html luis@1051: flash['notice'] = "OK!" luis@1051: format.js luis@947: end luis@1051: end luis@1051: end luis@947: luis@947: luis@1051: # respond_to do |format| luis@1051: # format.js { luis@1051: # render(:update) {|page| luis@1051: # flash.now[:notice] = "Correctly parsed BibTeX entry" luis@1051: # luis@1051: # bibtex_entry_no = BibtexEntryType.find_by_name(bib[0].type.to_s).id luis@1051: # page["publication_title"].value = bib[0][:title] luis@1051: # page["publication_bibtex_entry_attributes_entry_type"].value = #bibtex_entry_no luis@1051: # luis@1051: # BibtexEntryType.fields(bibtex_entry_no).each do |field| luis@1051: # page["publication_bibtex_entry_attributes_#{field}"].value = bib[0][field#] luis@1051: # end luis@1051: # luis@1051: # # for each author simulates a click and fills the author info luis@1051: ## bib[0].authors.each do |author| luis@1051: ## page["add_another_author"].click luis@1051: ## page.alert(bib[0].authors.length) luis@1051: ## page.alert(page["authors"].first.id) luis@1051: ## end luis@1051: # luis@1051: # luis@1051: # luis@1051: # } luis@1051: # } luis@1051: # end luis@951: luis@1051: # rescue BibtexParsingError => e luis@1051: # logger.error { "Bibtex Parsing Error #{bib.errors}" } luis@947: luis@947: # todo: not showing... should be inside render? luis@1051: # flash[:error] = e.message luis@947: luis@1051: # respond_to do |format| luis@1051: # format.js{ luis@1051: # render(:update) {|page| luis@1051: # } luis@1051: # } luis@1051: # end luis@947: luis@1051: # end luis@409: luis@947: luis@1051: luis@1051: def create luisf@613: @project = Project.find(params[:project_id]) luisf@613: chris@661: @author_options = [] luis@614: luis@390: @publication = Publication.new(params[:publication]) luis@553: @publication.projects << @project unless @project.nil? luis@946: luis@1051: if @publication.save luis@666: @publication.notify_authors_publication_added(@project) luis@946: luis@445: flash[:notice] = "Successfully created publication." luisf@613: redirect_to :action => :show, :id => @publication, :project_id => @project luis@445: else luisf@613: render :action => 'new', :project_id => @project luis@445: end luis@445: end luis@445: luis@445: def index luis@538: if !params[:project_id].nil? luis@538: find_project_by_project_id luis@538: @project = Project.find(params[:project_id]) luis@538: @publications = Publication.find :all, :joins => :projects, :conditions => ["project_id = ?", @project.id] luis@538: else luis@538: @publications = Publication.find :all luis@538: end luis@445: end luis@445: luis@445: def new_from_bibfile luis@391: @publication.current_step = session[:publication_step] luis@946: luis@404: # contents of the paste text area luis@404: bibtex_entry = params[:bibtex_entry] luis@384: luis@404: # method for creating "pasted" bibtex entries luis@424: if bibtex_entry luis@1051: parse_bibtex_list bibtex_entry luis@404: end luis@329: end luis@329: luis@675: def get_bibtex_required_fields luis@675: luis@1051: fields = BibtexEntryType.fields(params[:q]) luis@675: luis@675: respond_to do |format| luis@675: format.js { luis@1051: render(:update) {|page| luis@947: if params[:q].empty? luis@699: page << "hideOnLoad();" luis@699: else luis@699: page << "show_required_bibtex_fields(#{fields.to_json()});" luis@675: end luis@675: } luis@675: } luis@946: luis@675: end luis@675: end luis@675: luis@467: def add_author luis@467: if (request.xhr?) luis@467: render :text => User.find(params[:user_id]).name luis@467: else luis@467: # No? Then render an action. luis@467: #render :action => 'view_attribute', :attr => @name luis@675: logger.error { "Error while adding Author to publication." } luis@467: end luis@467: end luis@467: luis@1051: def edit luis@547: find_project_by_project_id unless params[:project_id].nil? luis@946: luis@609: @edit_view = true; luis@428: @publication = Publication.find(params[:id]) luis@626: @selected_bibtex_entry_type_id = @publication.bibtex_entry.entry_type luis@626: luis@1051: @author_options = [] luis@946: luis@1051: @bibtype_fields = BibtexEntryType.fields(@selected_bibtex_entry_type_id) luis@430: end luis@430: luis@1051: def update luis@1051: @publication = Publication.find(params[:id]) luis@538: chris@661: @author_options = [] luis@626: luis@430: if @publication.update_attributes(params[:publication]) luis@947: flash[:notice] = "Successfully Updated Publication." luis@538: luis@538: if !params[:project_id].nil? luis@538: redirect_to :action => :show, :id => @publication, :project_id => params[:project_id] luis@538: else luis@538: redirect_to :action => :show, :id => @publication luis@538: end luis@430: else luis@448: render :action => 'edit' luis@1051: end luis@328: end luis@328: luis@946: luis@425: def show luis@535: find_project_by_project_id unless params[:project_id].nil? luis@946: luis@425: if @publication.nil? luis@579: @publications = Publication.all luis@579: render "index", :alert => 'The publication was not found!' luis@425: else luis@425: @authors = @publication.authors luis@425: @bibtext_entry = @publication.bibtex_entry luis@425: end luis@329: end luis@329: luis@406: # parse string with bibtex authors luis@406: def parse_authors(authors_entry) luis@406: # in bibtex the authors are always seperated by "and" luis@407: return authors_entry.split(" and ") luis@406: end luis@406: luis@1051: # parses a list of bibtex luis@406: def parse_bibtex_list(bibtex_list) luis@406: bibliography = BibTeX.parse bibtex_list luis@406: luis@406: no_entries = bibliography.data.length luis@406: luis@406: # parses the bibtex entries luis@406: bibliography.data.map do |d| luis@407: luis@407: if d.class == BibTeX::Entry luis@407: create_bibtex_entry d luis@407: end luis@406: end luis@1051: end luis@407: luis@1051: def create_bibtex_entry(d) luis@407: @publication = Publication.new luis@1051: @bentry = BibtexEntry.new luis@407: authors = [] luis@407: institution = "" luis@407: email = "" luis@409: luis@407: d.fields.keys.map do |field| luis@407: case field.to_s luis@407: when "author" luis@407: authors = parse_authors d[field] luis@407: when "title" luis@407: @publication.title = d[field] luis@407: when "institution" luis@407: institution = d[field] luis@407: when "email" luis@407: email = d[field] luis@407: else luis@407: @bentry[field] = d[field] luis@407: end luis@1051: end luis@406: luis@406: @publication.bibtex_entry = @bentry luis@407: @publication.save luis@409: luis@1051: # what is this for??? luis@424: # @created_publications << @publication.id luis@409: luis@407: # need to save all authors luis@1051: # and establish the author-publication association luis@1051: # via the authorships table luis@407: authors.each_with_index.map do |authorname, idx| luis@407: author = Author.new(:name => authorname) luis@407: if author.save! luis@946: # todo: catch the errors... luis@407: puts "SAVED" luis@407: else luis@407: puts "NOT SAVED" luis@406: end luis@406: luis@407: author.authorships.create!( luis@946: :publication => @publication, luis@946: :institution => institution, luis@946: :email => email, luis@946: :order => idx) luis@407: end luis@407: end luis@409: luis@407: # parses the bibtex file luis@407: def parse_bibtex_file luis@407: luis@406: end luis@406: luis@444: def import luis@444: @publication = Publication.new luis@946: luis@946: luis@444: end luis@946: luis@461: def autocomplete_for_project luis@461: @publication = Publication.find(params[:id]) luis@946: luis@1051: @projects = Project.active.like(params[:q]).find(:all, :limit => 100) - @publication.projects luis@461: logger.debug "Query for \"#{params[:q]}\" returned \"#{@projects.size}\" results" luis@461: render :layout => false luis@409: end luis@471: luis@1051: luis@1051: def autocomplete_for_author luis@519: @results = [] luis@946: luis@596: object_id = params[:object_id] luis@598: @object_name = "publications[authorships_attributes][#{object_id}][search_results]" luis@946: Chris@674: # cc 20110909 -- revert to like instead of like_unique -- see #289 Chris@674: authorships_list = Authorship.like(params[:q]).find(:all, :limit => 100) luis@480: users_list = User.active.like(params[:q]).find(:all, :limit => 100) luis@480: luis@591: logger.debug "Query for \"#{params[:q]}\" returned \"#{authorships_list.size}\" authorships and \"#{users_list.size}\" users" luis@946: luis@601: @results = users_list luis@601: luis@1051: # TODO: can be optimized… luis@1051: authorships_list.each do |authorship| luis@601: flag = true luis@946: luis@601: users_list.each do |user| luis@601: if authorship.name == user.name && authorship.email == user.mail && authorship.institution == user.institution luis@601: Rails.logger.debug { "Rejecting Authorship #{authorship.id}" } luis@601: flag = false luis@601: break luis@601: end luis@601: end luis@601: luis@601: @results << authorship if flag luis@592: end luis@592: luis@1051: render :layout => false luis@598: end luis@946: luis@598: def get_user_info luis@598: object_id = params[:object_id] luis@598: value = params[:value] luis@598: classname = Kernel.const_get(value.split('_')[0]) luis@592: luis@598: item = classname.find(value.split('_')[1]) luis@598: luis@598: name_field = "publication_authorships_attributes_#{object_id}_name_on_paper".to_sym luis@598: email_field = "publication_authorships_attributes_#{object_id}_email".to_sym luis@600: institution_field = "publication_authorships_attributes_#{object_id}_institution".to_sym luis@946: luis@600: yes_radio = "publication_authorships_attributes_#{object_id}_identify_author_yes".to_sym luis@946: luis@598: respond_to do |format| luis@675: format.js { luis@1051: render(:update) {|page| luis@598: page[name_field].value = item.name luis@598: page[email_field].value = item.mail luis@600: page[institution_field].value = item.institution luis@600: luis@600: page[yes_radio].checked = true luis@601: page[name_field].readOnly = true luis@601: page[email_field].readOnly = true luis@601: page[institution_field].readOnly = true luis@598: } luis@598: } luis@598: end luis@477: end luis@471: luis@557: def sort_author_order luis@557: params[:authorships].each_with_index do |id, index| luis@557: Authorship.update_all(['auth_order=?', index+1], ['id=?', id]) luis@471: end luis@471: render :nothing => true luis@471: end luis@574: luis@574: def add_project luis@1051: @projects = Project.find(params[:publication][:project_ids]) luis@574: @publication.projects << @projects luis@1051: @project = Project.find(params[:project_id]) luis@946: luis@1051: # TODO luisf should also respond to HTML??? luis@574: respond_to do |format| luis@574: format.html { redirect_to :back } luis@1051: format.js { luis@1051: render(:update) {|page| luis@1051: page[:add_project_form].reset luis@574: page.replace_html :list_projects, :partial => 'list_projects' luis@574: } luis@574: } luis@574: end luis@574: end luis@946: luis@946: luis@574: def remove_project luis@579: @project = Project.find(params[:project_id]) luis@579: proj = Project.find(params[:remove_project_id]) luis@554: luis@574: if @publication.projects.length > 1 luis@579: if @publication.projects.exists? proj luis@579: @publication.projects.delete proj if request.post? luis@554: end luis@554: else luis@1051: logger.error { "Cannot remove project from publication list" } luis@554: end luis@946: luis@591: logger.error { "CURRENT project name#{proj.name} and wanna delete #{@project.name}" } luis@946: luis@1051: render(:update) {|page| luis@579: page.replace_html "list_projects", :partial => 'list_projects', :id => @publication luis@1051: } luis@554: end luis@946: luis@560: def destroy luis@560: find_project_by_project_id luis@946: luis@560: @publication.destroy luis@946: luis@560: flash[:notice] = "Successfully deleted Publication." luis@560: redirect_to :controller => :publications, :action => 'index', :project_id => @project luis@560: end luis@471: luis@538: private luis@478: luis@328: end