Mercurial > hg > soundsoftware-site
changeset 442:753f1380d6bc cannam
Merge from branch "redmine-1.2"
line wrap: on
line diff
--- a/app/controllers/account_controller.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/controllers/account_controller.rb Mon Jun 06 14:41:04 2011 +0100 @@ -77,13 +77,19 @@ # User self-registration def register redirect_to(home_url) && return unless Setting.self_registration? || session[:auth_source_registration] + if request.get? session[:auth_source_registration] = nil @user = User.new(:language => Setting.default_language) + + @ssamr_user_details = SsamrUserDetail.new + else @user = User.new(params[:user]) @user.admin = false + @user.register + if session[:auth_source_registration] @user.activate @user.login = session[:auth_source_registration][:login] @@ -98,6 +104,13 @@ @user.login = params[:user][:login] @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] + @ssamr_user_details = SsamrUserDetail.new(params[:ssamr_user_details]) + + # associates the 2 objects + @user.ssamr_user_detail = @ssamr_user_details + @selected_institution_id = params[:ssamr_user_details][:institution_id].to_i + + case Setting.self_registration when '1' register_by_email_activation(@user) @@ -269,6 +282,9 @@ # Pass a block for behavior when a user fails to save def register_manually_by_administrator(user, &block) if user.save + + @ssamr_user_details.save! + # Sends an email to the administrators Mailer.deliver_account_activation_request(user) account_pending
--- a/app/controllers/application_controller.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/controllers/application_controller.rb Mon Jun 06 14:41:04 2011 +0100 @@ -267,6 +267,12 @@ uri = URI.parse(back_url) # do not redirect user to another host or to the login or register page if (uri.relative? || (uri.host == request.host)) && !uri.path.match(%r{/(login|account/register)}) + # soundsoftware: if login page is https but back_url http, + # switch back_url to https to ensure cookie validity (#83) + if (uri.scheme == "http") && (URI.parse(request.url).scheme == "https") + uri.scheme = "https" + back_url = uri.to_s + end redirect_to(back_url) return end @@ -319,7 +325,7 @@ if api_request? logger.error "Form authenticity token is missing or is invalid. API calls must include a proper Content-type header (text/xml or text/json)." end - render_error "Invalid form authenticity token." + render_error "Invalid form authenticity token. Perhaps your session has timed out; try reloading the form and entering your details again." end def render_feed(items, options={})
--- a/app/controllers/issues_controller.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/controllers/issues_controller.rb Mon Jun 06 14:41:04 2011 +0100 @@ -140,7 +140,16 @@ attachments = Attachment.attach_files(@issue, params[:attachments]) render_attachment_warning_if_needed(@issue) flash[:notice] = l(:notice_successful_create) + call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue}) + + # Also adds the assignee to the watcher's list + if params[:issue][:assigned_to_id] && !params[:issue][:assigned_to_id].empty?: + unless @issue.watcher_ids.include?(params[:issue][:assigned_to_id]): + @issue.add_watcher(User.find(params[:issue][:assigned_to_id])) + end + end + respond_to do |format| format.html { redirect_to(params[:continue] ? { :action => 'new', :project_id => @project, :issue => {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} } : @@ -287,6 +296,18 @@ @notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil) @issue.init_journal(User.current, @notes) @issue.safe_attributes = params[:issue] + + # tests if the the user assigned_to_id + # is in this issues watcher's list + # if not, adds it. + + if params[:issue][:assigned_to_id] && !params[:issue][:assigned_to_id].empty?: + unless @issue.watched_by?(User.find(params[:issue][:assigned_to_id])): + @issue.add_watcher(User.find(params[:issue][:assigned_to_id])) + end + end + + end # TODO: Refactor, lots of extra code in here
--- a/app/controllers/members_controller.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/controllers/members_controller.rb Mon Jun 06 14:41:04 2011 +0100 @@ -94,6 +94,7 @@ def autocomplete_for_member @principals = Principal.active.like(params[:q]).find(:all, :limit => 100) - @project.principals + logger.debug "Query for #{params[:q]} returned #{@principals.size} results" render :layout => false end
--- a/app/controllers/my_controller.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/controllers/my_controller.rb Mon Jun 06 14:41:04 2011 +0100 @@ -53,10 +53,39 @@ def account @user = User.current @pref = @user.pref + @ssamr_user_details = @user.ssamr_user_detail + + + if @user.ssamr_user_detail == nil + @selected_institution_id = nil + else + @selected_institution_id = @ssamr_user_details.institution_id.to_i + end + if request.post? @user.safe_attributes = params[:user] @user.pref.attributes = params[:pref] @user.pref[:no_self_notified] = (params[:no_self_notified] == '1') + + if @user.ssamr_user_detail == nil + @ssamr_user_details = SsamrUserDetail.new() + @user.ssamr_user_detail = @ssamr_user_details + else + @ssamr_user_details = @user.ssamr_user_detail + end + + if params[:ssamr_user_details].nil? or params[:ssamr_user_details].empty? + @ssamr_user_details.description = @user.ssamr_user_detail.description + @ssamr_user_details.institution_id = @user.ssamr_user_detail.institution_id + @institution_type = @ssamr_user_details.institution_type + @other_institution = @ssamr_user_details.other_institution + else + @ssamr_user_details.description = params[:ssamr_user_details][:description] + @ssamr_user_details.institution_id = params[:ssamr_user_details][:institution_id] + @ssamr_user_details.institution_type = params[:ssamr_user_details][:institution_type] + @ssamr_user_details.other_institution = params[:ssamr_user_details][:other_institution] + end + if @user.save @user.pref.save @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
--- a/app/controllers/projects_controller.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/controllers/projects_controller.rb Mon Jun 06 14:41:04 2011 +0100 @@ -42,12 +42,23 @@ helper :repositories include RepositoriesHelper include ProjectsHelper - - # Lists visible projects + + # Lists visible projects. Paginator is for top-level projects only + # (subprojects belong to them) def index respond_to do |format| format.html { - @projects = Project.visible.find(:all, :order => 'lft') + sort_init 'name' + sort_update %w(name lft created_on updated_on) + @limit = per_page_option + @project_count = Project.visible_roots.count + @project_pages = Paginator.new self, @project_count, @limit, params['page'] + @offset ||= @project_pages.current.offset + @projects = Project.visible_roots.all(:offset => @offset, :limit => @limit, :order => sort_clause) + if User.current.logged? + @user_projects = User.current.projects.sort_by(&:name) + end + render :template => 'projects/index.rhtml', :layout => !request.xhr? } format.api { @offset, @limit = api_offset_and_limit
--- a/app/controllers/sys_controller.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/controllers/sys_controller.rb Mon Jun 06 14:41:04 2011 +0100 @@ -55,6 +55,31 @@ render :nothing => true, :status => 404 end + def set_embedded_active + project = Project.find(params[:id]) + mods = project.enabled_modules + enable = (params[:enable] == "1") + if mods.detect {|m| m.name == "embedded"} + logger.info "Project #{project.name} currently has Embedded enabled" + if !enable + logger.info "Disabling Embedded" + modnames = mods.all(:select => :name).collect{|m| m.name}.reject{|n| n == "embedded"} + project.enabled_module_names = modnames + end + else + logger.info "Project #{project.name} currently has Embedded disabled" + if enable + logger.info "Enabling Embedded" + modnames = mods.all(:select => :name).collect{|m| m.name} + modnames << "embedded" + project.enabled_module_names = modnames + end + end + render :nothing => true, :status => 200 + rescue ActiveRecord::RecordNotFound + render :nothing => true, :status => 404 + end + protected def check_enabled
--- a/app/controllers/users_controller.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/controllers/users_controller.rb Mon Jun 06 14:41:04 2011 +0100 @@ -68,6 +68,20 @@ end def show + + if @user.ssamr_user_detail != nil + @description = @user.ssamr_user_detail.description + + if @user.ssamr_user_detail.institution_type != nil + # institution_type is true for listed institutions + if (@user.ssamr_user_detail.institution_type) + @institution_name = Institution.find(@user.ssamr_user_detail.institution_id).name + else + @institution_name = @user.ssamr_user_detail.other_institution + end + end + end + # show projects based on current user visibility @memberships = @user.memberships.all(:conditions => Project.visible_condition(User.current)) @@ -87,15 +101,18 @@ end end - def new + def new @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option) @auth_sources = AuthSource.find(:all) + + @ssamr_user_details = SsamrUserDetail.new end verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed } def create @user = User.new(:language => Setting.default_language, :mail_notification => Setting.default_notification_option) @user.safe_attributes = params[:user] + @user = User.new(params[:user]) @user.admin = params[:user][:admin] || false @user.login = params[:user][:login] @user.password, @user.password_confirmation = params[:user][:password], params[:user][:password_confirmation] unless @user.auth_source_id @@ -104,9 +121,16 @@ @user.pref.attributes = params[:pref] @user.pref[:no_self_notified] = (params[:no_self_notified] == '1') + @ssamr_user_details = SsamrUserDetail.new(params[:ssamr_user_details]) + + # associates the 2 objects + @user.ssamr_user_detail = @ssamr_user_details + if @user.save @user.pref.save - @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : []) + + @ssamr_user_details.save! + Mailer.deliver_account_information(@user, params[:user][:password]) if params[:send_information] @@ -133,6 +157,15 @@ end def edit + + @ssamr_user_details = @user.ssamr_user_detail + + if @user.ssamr_user_detail == nil + @selected_institution_id = nil + else + @selected_institution_id = @user.ssamr_user_detail.institution_id.to_i + end + @auth_sources = AuthSource.find(:all) @membership ||= Member.new end @@ -151,6 +184,26 @@ @user.pref.attributes = params[:pref] @user.pref[:no_self_notified] = (params[:no_self_notified] == '1') + if @user.ssamr_user_detail == nil + @ssamr_user_details = SsamrUserDetail.new() + @user.ssamr_user_detail = @ssamr_user_details + else + @ssamr_user_details = @user.ssamr_user_detail + end + + if params[:ssamr_user_details].nil? or params[:ssamr_user_details].empty? + @ssamr_user_details.description = @user.ssamr_user_detail.description + @ssamr_user_details.institution_id = @user.ssamr_user_detail.institution_id + @ssamr_user_details.other_institution = @user.ssamr_user_detail.other_institution + @ssamr_user_details.institution_type = @user.ssamr_user_detail.institution_type + + else + @ssamr_user_details.description = params[:ssamr_user_details][:description] + @ssamr_user_details.institution_id = params[:ssamr_user_details][:institution_id] + @ssamr_user_details.other_institution = params[:ssamr_user_details][:other_institution] + @ssamr_user_details.institution_type = params[:ssamr_user_details][:institution_type] + end + if @user.save @user.pref.save @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : [])
--- a/app/controllers/welcome_controller.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/controllers/welcome_controller.rb Mon Jun 06 14:41:04 2011 +0100 @@ -21,6 +21,14 @@ def index @news = News.latest User.current @projects = Project.latest User.current + + # tests if user is logged in to gfenerate the tips of the day list + if User.current.logged? + @tipsoftheday = Setting.tipoftheday_text + else + @tipsoftheday = '' + end + end def robots
--- a/app/helpers/application_helper.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/helpers/application_helper.rb Mon Jun 06 14:41:04 2011 +0100 @@ -52,7 +52,7 @@ if user.is_a?(User) name = h(user.name(options[:format])) if user.active? - link_to name, :controller => 'users', :action => 'show', :id => user + link_to(name, :controller => 'users', :action => 'show', :id => user) else name end @@ -287,7 +287,7 @@ def principals_check_box_tags(name, principals) s = '' principals.sort.each do |principal| - s << "<label>#{ check_box_tag name, principal.id, false } #{h principal}</label>\n" + s << "<label>#{ check_box_tag name, principal.id, false } #{link_to_user principal}</label>\n" end s end @@ -387,21 +387,28 @@ def page_header_title if @project.nil? || @project.new_record? - h(Setting.app_title) + a = [h(Setting.app_title), ''] + else + pname = [] b = [] ancestors = (@project.root? ? [] : @project.ancestors.visible.all) if ancestors.any? root = ancestors.shift b << link_to_project(root, {:jump => current_menu_item}, :class => 'root') if ancestors.size > 2 - b << '…' + b << '…' ancestors = ancestors[-2, 2] end b += ancestors.collect {|p| link_to_project(p, {:jump => current_menu_item}, :class => 'ancestor') } + b = b.join(' » ') + b << (' »') end - b << h(@project) - b.join(' » ') + + pname << h(@project) + + a = [pname, b] + end end
--- a/app/helpers/projects_helper.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/helpers/projects_helper.rb Mon Jun 06 14:41:04 2011 +0100 @@ -83,6 +83,160 @@ s end + + # Renders a tree of projects where the current user belongs + # as a nested set of unordered lists + # The given collection may be a subset of the whole project tree + # (eg. some intermediate nodes are private and can not be seen) + def render_my_project_hierarchy(projects) + s = '' + + a = '' + + # Flag to tell if user has any projects + t = FALSE + + if projects.any? + ancestors = [] + original_project = @project + projects.each do |project| + # set the project environment to please macros. + + @project = project + + if User.current.member_of?(project): + + t = TRUE + + if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) + s << "<ul class='projects #{ ancestors.empty? ? 'root' : nil}'>\n" + else + ancestors.pop + s << "</li>" + while (ancestors.any? && !project.is_descendant_of?(ancestors.last)) + ancestors.pop + s << "</ul></li>\n" + end + end + + classes = (ancestors.empty? ? 'root' : 'child') + s << "<li class='#{classes}'><div class='#{classes}'>" + + link_to_project(project, {}, :class => "project my-project") + if project.is_public? + s << " <span class='public'>" << l("field_is_public") << "</span>" + else + s << " <span class='private'>" << l("field_is_private") << "</span>" + end + s << "<div class='wiki description'>#{textilizable(project.short_description, :project => project)}</div>" unless project.description.blank? + s << "</div>\n" + ancestors << project + end + end + s << ("</li></ul>\n" * ancestors.size) + @project = original_project + end + + if t == TRUE + a << "<h2>" + a << l("label_my_project_plural") + a << "</h2>" + a << s + else + a = s + end + + a + end + + # Renders a tree of projects that the current user does not belong + # to, or of all projects if the current user is not logged in. The + # given collection may be a subset of the whole project tree + # (eg. some intermediate nodes are private and can not be seen). We + # are potentially interested in various things: the project name, + # description, manager(s), creation date, last activity date, + # general activity level, whether there is anything actually hosted + # here for the project, etc. + def render_project_table(projects) + + s = "" + s << "<div class='autoscroll'>" + s << "<table class='list projects'>" + s << "<thead><tr>" + + s << sort_header_tag('name', :caption => l("field_name")) + s << "<th class='managers'>" << l("label_managers") << "</th>" + s << sort_header_tag('created_on', :default_order => 'desc') + s << sort_header_tag('updated_on', :default_order => 'desc') + + s << "</tr></thead><tbody>" + + original_project = @project + + projects.each do |project| + s << render_project_in_table(project, cycle('odd', 'even'), 0) + end + + s << "</table>" + + @project = original_project + + s + end + + + def render_project_in_table(project, oddeven, level) + + # set the project environment to please macros. + @project = project + + classes = (level == 0 ? 'root' : 'child') + + s = "" + + s << "<tr class='#{oddeven} #{classes} level#{level}'>" + s << "<td class='firstcol' align=top><div class='name hosted_here" + s << " no_description" if project.description.blank? + s << "'>" << link_to_project(project, {}, :class => "project #{User.current.member_of?(project) ? 'my-project' : nil}"); + s << "</div>" + unless project.description.blank? + s << "<div class='wiki description'>" + s << textilizable(project.short_description, :project => project) + s << "</div>" + end + + s << "<td class='managers' align=top>" + + u = project.users_by_role + if u + u.keys.each do |r| + if r.allowed_to?(:edit_project) + mgrs = [] + u[r].sort.each do |m| + mgrs << link_to_user(m) + end + if mgrs.size < 3 + s << '<nobr>' << mgrs.join(', ') << '</nobr>' + else + s << mgrs.join(', ') + end + end + end + end + + s << "</td>" + s << "<td class='created_on' align=top>" << format_date(project.created_on) << "</td>" + s << "<td class='updated_on' align=top>" << format_date(project.updated_on) << "</td>" + + s << "</tr>" + + project.children.each do |child| + s << render_project_in_table(child, oddeven, level + 1) + end + + s + end + + # Returns a set of options for a select field, grouped by project. def version_options_for_select(versions, selected=nil) grouped = Hash.new {|h,k| h[k] = []}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/models/institution.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,2 @@ +class Institution < ActiveRecord::Base +end
--- a/app/models/issue.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/models/issue.rb Mon Jun 06 14:41:04 2011 +0100 @@ -564,7 +564,8 @@ # Returns a string of css classes that apply to the issue def css_classes - s = "issue status-#{status.position} priority-#{priority.position}" + s = "issue status-#{status.position} " + s << "priority-#{priority.position}" s << ' closed' if closed? s << ' overdue' if overdue? s << ' child' if child?
--- a/app/models/project.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/models/project.rb Mon Jun 06 14:41:04 2011 +0100 @@ -85,6 +85,7 @@ named_scope :active, { :conditions => "#{Project.table_name}.status = #{STATUS_ACTIVE}"} named_scope :all_public, { :conditions => { :is_public => true } } named_scope :visible, lambda {|*args| {:conditions => Project.visible_condition(args.shift || User.current, *args) }} + named_scope :visible_roots, lambda { { :conditions => Project.root_visible_by(User.current) } } def initialize(attributes = nil) super @@ -133,6 +134,10 @@ allowed_to_condition(user, :view_project, options) end + def self.root_visible_by(user=nil) + return "#{Project.table_name}.parent_id IS NULL AND " + visible_by(user) + end + # Returns a SQL conditions string used to find all projects for which +user+ has the given +permission+ # # Valid options: @@ -463,7 +468,14 @@ # Returns a short description of the projects (first lines) def short_description(length = 255) - description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description + ## Original Redmine code: this truncates to the CR that is more + ## than "length" characters from the start. + # description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description + ## That's too much for us, and also we want to omit images and the + ## like. Truncate instead to the first CR that follows _any_ + ## non-blank text, and to the next word break beyond "length" + ## characters if the result is still longer than that. + description.gsub(/![^\s]+!/, '').gsub(/^(\s*[^\n\r]*).*$/m, '\1').gsub(/^(.{#{length}}\b).*$/m, '\1 ...').strip if description end def css_classes
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/models/repository/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,47 @@ +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/4982/trunk/app/models/repository +END +subversion.rb +K 25 +svn:wc:ra_dav:version-url +V 60 +/svn/!svn/ver/4962/trunk/app/models/repository/subversion.rb +END +bazaar.rb +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/4982/trunk/app/models/repository/bazaar.rb +END +git.rb +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/4975/trunk/app/models/repository/git.rb +END +mercurial.rb +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/4975/trunk/app/models/repository/mercurial.rb +END +filesystem.rb +K 25 +svn:wc:ra_dav:version-url +V 60 +/svn/!svn/ver/4975/trunk/app/models/repository/filesystem.rb +END +cvs.rb +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/4982/trunk/app/models/repository/cvs.rb +END +darcs.rb +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/4982/trunk/app/models/repository/darcs.rb +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/models/ssamr_user_detail.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,14 @@ +class SsamrUserDetail < ActiveRecord::Base + belongs_to :user + + validates_presence_of :description + + validate :check_institution + + def check_institution() + errors.add(:institution_id, "Please insert an institution") if + institution_id.blank? and other_institution.blank? + end + + +end
--- a/app/models/user.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/app/models/user.rb Mon Jun 06 14:41:04 2011 +0100 @@ -52,6 +52,9 @@ has_one :api_token, :class_name => 'Token', :conditions => "action='api'" belongs_to :auth_source + has_one :ssamr_user_detail, :dependent => :destroy, :class_name => 'SsamrUserDetail' + accepts_nested_attributes_for :ssamr_user_detail + # Active non-anonymous users scope named_scope :active, :conditions => "#{User.table_name}.status = #{STATUS_ACTIVE}" @@ -63,6 +66,9 @@ attr_protected :login, :admin, :password, :password_confirmation, :hashed_password validates_presence_of :login, :firstname, :lastname, :mail, :if => Proc.new { |user| !user.is_a?(AnonymousUser) } + + # TODO: is this validation correct validates_presence_of :ssamr_user_detail + validates_uniqueness_of :login, :if => Proc.new { |user| !user.login.blank? }, :case_sensitive => false validates_uniqueness_of :mail, :if => Proc.new { |user| !user.mail.blank? }, :case_sensitive => false # Login must contain lettres, numbers, underscores only @@ -76,6 +82,8 @@ before_destroy :remove_references_before_destroy + validates_acceptance_of :terms_and_conditions, :on => :create, :message => :must_accept_terms_and_conditions + named_scope :in_group, lambda {|group| group_id = group.is_a?(Group) ? group.id : group.to_i { :conditions => ["#{User.table_name}.id IN (SELECT gu.user_id FROM #{table_name_prefix}groups_users#{table_name_suffix} gu WHERE gu.group_id = ?)", group_id] } @@ -107,6 +115,10 @@ write_attribute(:mail, arg.to_s.strip) end + def description=(arg) + write_attribute(:description, arg.to_s.strip) + end + def identity_url=(url) if url.blank? write_attribute(:identity_url, '')
--- a/app/views/account/register.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/account/register.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -1,3 +1,6 @@ +<%= javascript_include_tag "ssamr_institutions" %> +<%= javascript_include_tag "ssamr_registration" %> + <h2><%=l(:label_register)%> <%=link_to l(:label_login_with_open_id_option), signin_url if Setting.openid? %></h2> <% form_tag({:action => 'register'}, :class => "tabular") do %> @@ -29,6 +32,26 @@ <p><label for="user_language"><%=l(:field_language)%></label> <%= select("user", "language", lang_options_for_select) %></p> + +<h3><%=l(:label_ssamr_details)%></h3> + + <% fields_for :ssamr_user_details, :builder => TabularFormBuilder, :lang => current_language do |ssamr_user_detail| %> + <p> + <%= ssamr_user_detail.text_area :description, :rows => 3, :cols => 40, :required => true, :class => 'wiki-edit' %> + <em> <%=l(:text_user_ssamr_description_info)%></em> + </p> + + <p><label for="institution"><%=l("field_ssamr_user_detail.institution")%> <span class="required">*</span></label> + <%= ssamr_user_detail.radio_button :institution_type, true %> + <%= ssamr_user_detail.collection_select(:institution_id, Institution.find(:all, :order => "institutions.order"), :id, :name, {:selected => @selected_institution_id, :prompt => true}).gsub('&', '&') %> + </p> + + <p> + <%= ssamr_user_detail.radio_button :institution_type, false %> Other: + <%= ssamr_user_detail.text_field(:other_institution) %> + </p> + <% end %> + <% if Setting.openid? %> <p><label for="user_identity_url"><%=l(:field_identity_url)%></label> <%= text_field 'user', 'identity_url' %></p> @@ -40,5 +63,9 @@ <!--[eoform:user]--> </div> +<%= check_box :user, :terms_and_conditions %> <%= l(:accept_terms_and_conditions) %> <%= link_to("Terms and Conditions", "https://code.soundsoftware.ac.uk/projects/soundsoftware-site/wiki/TandCs", {:target => "_blank"}) %>. +<br /> +<br /> + <%= submit_tag l(:button_submit) %> <% end %>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/views/gantts/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 41 +/svn/!svn/ver/4913/trunk/app/views/gantts +END +show.html.erb +K 25 +svn:wc:ra_dav:version-url +V 55 +/svn/!svn/ver/4913/trunk/app/views/gantts/show.html.erb +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/views/issue_moves/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 46 +/svn/!svn/ver/4583/trunk/app/views/issue_moves +END +new.rhtml +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/!svn/ver/4583/trunk/app/views/issue_moves/new.rhtml +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/views/issue_relations/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/4502/trunk/app/views/issue_relations +END +_form.rhtml +K 25 +svn:wc:ra_dav:version-url +V 62 +/svn/!svn/ver/4502/trunk/app/views/issue_relations/_form.rhtml +END
--- a/app/views/issues/_attributes.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/issues/_attributes.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -8,7 +8,7 @@ <% end %> <p><%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), {:required => true}, :disabled => !@issue.leaf? %></p> -<p><%= f.select :assigned_to_id, (@issue.assignable_users.collect {|m| [m.name, m.id]}), :include_blank => true %></p> +<p><%= f.select :assigned_to_id, (@issue.assignable_users.collect {|m| [m.name, m.id]}), {:include_blank => true} %></p> <% unless @project.issue_categories.empty? %> <p><%= f.select :category_id, (@project.issue_categories.collect {|c| [c.name, c.id]}), :include_blank => true %> <%= prompt_to_remote(image_tag('add.png', :style => 'vertical-align: middle;'),
--- a/app/views/issues/_form.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/issues/_form.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -12,6 +12,7 @@ :with => "Form.serialize('issue-form')" %> <p><%= f.text_field :subject, :size => 80, :required => true %></p> + <p><%= f.text_area :description, :cols => 60, :rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min), @@ -30,7 +31,7 @@ <% if @issue.new_record? && User.current.allowed_to?(:add_issue_watchers, @project) -%> <p id="watchers_form"><label><%= l(:label_issue_watchers) %></label> <% @issue.project.users.sort.each do |user| -%> -<label class="floating"><%= check_box_tag 'issue[watcher_user_ids][]', user.id, @issue.watched_by?(user) %> <%=h user %></label> +<label class="floating"><%= check_box_tag 'issue[watcher_user_ids][]', user.id, !!(@issue.watched_by?(user) or user == User.current) %> <%=h user %></label> <% end -%> </p> <% end %>
--- a/app/views/layouts/base.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/layouts/base.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -3,8 +3,8 @@ <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title><%=h html_title %></title> -<meta name="description" content="<%= Redmine::Info.app_name %>" /> -<meta name="keywords" content="issue,bug,tracker" /> +<meta name="description" content="A repository for software developed and published by audio and music researchers in the UK." /> +<meta name="keywords" content="audio,music,software,research,UK,sound,repository,code,redmine" /> <%= csrf_meta_tag %> <%= favicon %> <%= stylesheet_link_tag 'application', :media => 'all' %> @@ -32,19 +32,33 @@ <%= render_menu :top_menu if User.current.logged? || !Setting.login_required? -%> </div> -<div id="header"> +<%= tag('div', {:id => 'header', :class => (display_main_menu?(@project) ? 'header-project' : 'header-general')}, true) %> <% if User.current.logged? || !Setting.login_required? %> - <div id="quick-search"> - <% form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %> - <%= hidden_field_tag(controller.default_search_scope, 1, :id => nil) if controller.default_search_scope %> - <%= link_to l(:label_search), {:controller => 'search', :action => 'index', :id => @project}, :accesskey => accesskey(:search) %>: - <%= text_field_tag 'q', @question, :size => 20, :class => 'small', :accesskey => accesskey(:quick_search) %> - <% end %> + + <div id="project-search-jump"> + <div id="quick-search"> + <% form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %> + <%= hidden_field_tag(controller.default_search_scope, 1, :id => nil) if controller.default_search_scope %> + <%= link_to l(:label_search), {:controller => 'search', :action => 'index', :id => @project}, :accesskey => accesskey(:search) %>: + <%= text_field_tag 'q', @question, :size => 20, :class => 'small', :accesskey => accesskey(:quick_search) %> + <% end %> + </div> + + <div id="project-jump-box"> <%= render_project_jump_box %> + </div> </div> <% end %> - - <h1><%= page_header_title %></h1> + + <% unless page_header_title[1].empty? %> + <h3 id="project-ancestors-title"><%= page_header_title[1] %></h3> + <% end %> + + <h1 id="project-title" + <% unless page_header_title[1].empty? %> + style="margin-top: 0px; " + <% end %> + ><%= page_header_title[0] %></h1> <% if display_main_menu?(@project) %> <div id="main-menu">
--- a/app/views/mailer/account_activation_request.text.html.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/mailer/account_activation_request.text.html.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -1,2 +1,12 @@ <p><%= l(:mail_body_account_activation_request, h(@user.login)) %></p> <p><%= link_to @url, @url %></p> + +<h3><%= l(:label_ssamr_details) %></h3> +<p> + <%=l(:field_name)%>: <%= h @user.name %><br /> + <%=l(:field_mail)%>: <%= h @user.mail %> +</p> + +<h4><%= l(:label_ssamr_description ) %></h4> +<%= textilizable @user.ssamr_user_detail['description'] %> +
--- a/app/views/mailer/account_activation_request.text.plain.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/mailer/account_activation_request.text.plain.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -1,2 +1,11 @@ <%= l(:mail_body_account_activation_request, @user.login) %> <%= @url %> + +*<%= l(:label_ssamr_details) %>* +<%=l(:field_name)%>: <%= h @user.name %> +<%=l(:field_mail)%>: <%= h @user.mail %> + +*<%= l(:label_ssamr_description ) %>* +<%= h @user.ssamr_user_detail['description'] %> + +
--- a/app/views/members/autocomplete_for_member.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/members/autocomplete_for_member.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -1,1 +1,3 @@ -<%= principals_check_box_tags 'member[user_ids][]', @principals %> \ No newline at end of file +<% if params[:q] && params[:q].length > 1 %> +<%= principals_check_box_tags 'member[user_ids][]', @principals %> +<% end %>
--- a/app/views/my/account.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/my/account.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -1,3 +1,5 @@ +<%= javascript_include_tag "ssamr_institutions" %> + <div class="contextual"> <%= link_to(l(:button_change_password), :action => 'password') if @user.change_password_allowed? %> <%= call_hook(:view_my_account_contextual, :user => @user)%> @@ -9,6 +11,8 @@ :builder => TabularFormBuilder, :lang => current_language, :html => { :id => 'my_account_form' } do |f| %> + + <div class="splitcontentleft"> <h3><%=l(:label_information_plural)%></h3> <div class="box tabular"> @@ -23,9 +27,35 @@ <% @user.custom_field_values.select(&:editable?).each do |value| %> <p><%= custom_field_tag_with_label :user, value %></p> <% end %> + <%= call_hook(:view_my_account, :user => @user, :form => f) %> </div> +<h3><%=l(:label_ssamr_details)%></h3> +<div class="box tabular"> + <% fields_for :ssamr_user_details, :builder => TabularFormBuilder, :lang => current_language do |ssamr_user_detail| %> + <p> + <%= ssamr_user_detail.text_area :description, :rows => 3, :cols => 25, :required => true, :class => 'wiki-edit' %> + </p> + + + <p><label for="institution"><%=l("field_ssamr_user_detail.institution")%> <span class="required">*</span></label> + <nobr> + <%= ssamr_user_detail.radio_button :institution_type, true %> + <%= ssamr_user_detail.collection_select(:institution_id, Institution.find(:all, :order => "institutions.order"), :id, :name, {:selected => @selected_institution_id, :prompt => true} ).gsub('&', '&') %> + </nobr> + </p> + + <p> + <nobr> + <%= ssamr_user_detail.radio_button :institution_type, false %> Other: + <%= ssamr_user_detail.text_field :other_institution, :size => 19 %> + </nobr> + </p> + <% end %> +</div> + + <%= submit_tag l(:button_save) %> </div> @@ -43,6 +73,14 @@ </div> <% end %> + + + + + + + + <% content_for :sidebar do %> <%= render :partial => 'sidebar' %> <% end %>
--- a/app/views/projects/_form.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/projects/_form.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -2,7 +2,10 @@ <div class="box"> <!--[form:project]--> -<p><%= f.text_field :name, :required => true, :size => 60 %></p> +<p><%= f.text_field :name, :required => true, :size => 60 %> + <br /> + <em> <%= l(:text_project_name_info) %></em> +</p> <% unless @project.allowed_parents.compact.empty? %> <p><%= label(:project, :parent_id, l(:field_parent)) %><%= parent_project_select_tag(@project) %></p> @@ -11,10 +14,17 @@ <p><%= f.text_area :description, :rows => 5, :class => 'wiki-edit' %></p> <p><%= f.text_field :identifier, :required => true, :size => 60, :disabled => @project.identifier_frozen? %> <% unless @project.identifier_frozen? %> -<br /><em><%= l(:text_length_between, :min => 1, :max => Project::IDENTIFIER_MAX_LENGTH) %> <%= l(:text_project_identifier_info) %></em> + <br /> + <em><%= l(:text_length_between, :min => 1, :max => Project::IDENTIFIER_MAX_LENGTH) %> <%= l(:text_project_identifier_info) %></em> <% end %></p> -<p><%= f.text_field :homepage, :size => 60 %></p> -<p><%= f.check_box :is_public %></p> +<p><%= f.text_field :homepage, :size => 60 %> +<br /> + <em> <%= l(:text_project_homepage_info) %></em> +</p> +<p><%= f.check_box :is_public %> +<br /> + <em> <%= l(:text_project_visibility_info) %></em> +</p> <%= wikitoolbar_for 'project_description' %> <% @project.custom_field_values.each do |value| %>
--- a/app/views/projects/index.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/projects/index.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -3,21 +3,25 @@ <% end %> <div class="contextual"> - <%= link_to(l(:label_project_new), {:controller => 'projects', :action => 'new'}, :class => 'icon icon-add') + ' |' if User.current.allowed_to?(:add_project, nil, :global => true) %> - <%= link_to(l(:label_issue_view_all), { :controller => 'issues' }) + ' |' if User.current.allowed_to?(:view_issues, nil, :global => true) %> - <%= link_to(l(:label_overall_spent_time), { :controller => 'time_entries' }) + ' |' if User.current.allowed_to?(:view_time_entries, nil, :global => true) %> <%= link_to l(:label_overall_activity), { :controller => 'activities', :action => 'index' }%> + <%= '| ' + link_to(l(:label_issue_view_all), { :controller => 'issues' }) if User.current.allowed_to?(:view_issues, nil, :global => true) %> + <%= '| ' + link_to(l(:label_project_new), {:controller => 'projects', :action => 'new'}, :class => 'icon icon-add') if User.current.allowed_to?(:add_project, nil, :global => true) %> </div> -<h2><%=l(:label_project_plural)%></h2> +<% if @user_projects %> + + <%= render_my_project_hierarchy(@user_projects)%> -<%= render_project_hierarchy(@projects)%> +<% end %> -<% if User.current.logged? %> -<p style="text-align:right;"> -<span class="my-project"><%= l(:label_my_projects) %></span> -</p> -<% end %> +<h2> +<%= l("label_project_all") %> +</h2> + +<%= render_project_table(@projects) %> + +<p class="pagination"><%= pagination_links_full @project_pages, @project_count %></p> + <% other_formats_links do |f| %> <%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %>
--- a/app/views/projects/settings/_members.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/projects/settings/_members.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -13,19 +13,18 @@ </tr></thead> <tbody> <% members.each do |member| %> - <% next if member.new_record? %> - <tr id="member-<%= member.id %>" class="<%= cycle 'odd', 'even' %> member"> - <td class="<%= member.principal.class.name.downcase %>"><%= link_to_user member.principal %></td> - <td class="roles"> - <span id="member-<%= member.id %>-roles"><%=h member.roles.sort.collect(&:to_s).join(', ') %></span> - <% if authorize_for('members', 'edit') %> - <% remote_form_for(:member, member, :url => {:controller => 'members', :action => 'edit', :id => member}, - :method => :post, - :html => { :id => "member-#{member.id}-roles-form", :class => 'hol' }) do |f| %> - <p><% roles.each do |role| %> - <label><%= check_box_tag 'member[role_ids][]', role.id, member.roles.include?(role), + <% next if member.new_record? %> + <tr id="member-<%= member.id %>" class="<%= cycle 'odd', 'even' %> member"> + <td class="<%= member.principal.class.name.downcase %>"><%= link_to_user member.principal %></td> + <td class="roles"> + <span id="member-<%= member.id %>-roles"><%=h member.roles.sort.collect(&:to_s).join(', ') %></span> + <% if authorize_for('members', 'edit') %> + <% remote_form_for(:member, member, :url => {:controller => 'members', :action => 'edit', :id => member}, + :method => :post, :html => { :id => "member-#{member.id}-roles-form", :class => 'hol' }) do |f| %> + <p><% roles.each do |role| %> + <label><%= check_box_tag 'member[role_ids][]', role.id, member.roles.include?(role), :disabled => member.member_roles.detect {|mr| mr.role_id == role.id && !mr.inherited_from.nil?} %> <%=h role %></label><br /> - <% end %></p> + <% end %></p> <%= hidden_field_tag 'member[role_ids][]', '' %> <p><%= submit_tag l(:button_change), :class => "small" %> <%= link_to_function l(:button_cancel), "$('member-#{member.id}-roles').show(); $('member-#{member.id}-roles-form').hide(); return false;" %></p> @@ -67,9 +66,11 @@ :url => { :controller => 'members', :action => 'autocomplete_for_member', :id => @project }, :with => 'q') %> - + <div id="principals"> - <%= principals_check_box_tags 'member[user_ids][]', principals %> + <% if params[:q] && params[:q].length > 1 %> + <%= principals_check_box_tags 'member[user_ids][]', @principals %> + <% end %> </div> <p><%= l(:label_role_plural) %>:
--- a/app/views/projects/settings/_repository.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/projects/settings/_repository.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -6,18 +6,11 @@ <%= error_messages_for 'repository' %> <div class="box tabular"> -<p> -<%= label_tag('repository_scm', l(:label_scm)) %><%= scm_select_tag(@repository) %> -<% if @repository && ! @repository.class.scm_available %> - <br /> - <em><%= content_tag 'span', l(:text_scm_command_not_available), :class => 'error' %></em> +<% if !@repository || !@repository.url %> +<ul><li><%= l(:text_settings_repo_creation) %></li></ul> <% end %> -</p> -<% button_disabled = true %> -<% if @repository %> -<% button_disabled = ! @repository.class.scm_available %> -<%= repository_field_tags(f, @repository)%> -<% end %> +<p><%= label_tag('repository_scm', l(:label_scm)) %><%= scm_select_tag(@repository) %></p> +<%= repository_field_tags(f, @repository) if @repository %> </div> <div class="contextual"> @@ -36,6 +29,5 @@ <% end %> </div> -<%= submit_tag((@repository.nil? || @repository.new_record?) ? l(:button_create) : l(:button_save), - :disabled => button_disabled) %> +<%= submit_tag((@repository.nil? || @repository.new_record?) ? l(:button_create) : l(:button_save), :disabled => @repository.nil?) %> <% end %>
--- a/app/views/settings/_general.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/settings/_general.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -3,10 +3,16 @@ <div class="box tabular settings"> <p><%= setting_text_field :app_title, :size => 30 %></p> +<p><%= setting_text_area :notifications_text, :cols => 60, :rows => 5, :class => 'wiki-edit' %></p> + <%= wikitoolbar_for 'settings_notifications_text' %> + <p><%= setting_text_area :welcome_text, :cols => 60, :rows => 5, :class => 'wiki-edit' %></p> <%= wikitoolbar_for 'settings_welcome_text' %> <p><%= setting_text_field :attachment_max_size, :size => 6 %> <%= l(:"number.human.storage_units.units.kb") %></p> + <%= wikitoolbar_for 'settings_tipoftheday_text' %> + +<p><%= setting_text_field :attachment_max_size, :size => 6 %> <%= l(:"number.human.storage_units.units.kb") %></p> <p><%= setting_text_field :per_page_options, :size => 20 %><br /> <em><%= l(:text_comma_separated) %></em></p>
--- a/app/views/users/_form.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/users/_form.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -1,3 +1,6 @@ +<%= javascript_include_tag "ssamr_institutions" %> + + <%= error_messages_for 'user' %> <div id="user_form"> @@ -22,6 +25,33 @@ <%= call_hook(:view_users_form, :user => @user, :form => f) %> </div> +<div class="box tabular"> + <h3><%=l(:label_ssamr_details)%></h3> + <% fields_for :ssamr_user_details, :builder => TabularFormBuilder, :lang => current_language do |ssamr_user_detail| %> + <p> + <%= ssamr_user_detail.text_area :description, :rows => 3, :cols => 40, :required => true, :class => 'wiki-edit' %> + </p> + + <p><label for="institution"><%=l("field_ssamr_user_detail.institution")%> <span class="required">*</span></label> + <nobr> + <%= ssamr_user_detail.radio_button :institution_type, true %> + <%= ssamr_user_detail.collection_select(:institution_id, Institution.find(:all, :order => "institutions.order"), :id, :name, {:selected => @selected_institution_id, :prompt => true} ).gsub('&', '&') %> + </nobr> + </p> + + + + <p> + <nobr> + <%= ssamr_user_detail.radio_button :institution_type, false %> Other: + <%= ssamr_user_detail.text_field :other_institution %> + </nobr> + </p> + <% end %> +</div> + + + <h3><%=l(:label_authentication)%></h3> <div class="box tabular"> <% unless @auth_sources.empty? %>
--- a/app/views/users/show.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/users/show.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -20,6 +20,13 @@ <% end %> </ul> +<h3><%=l(:label_ssamr_description)%></h3> +<%= textilizable @description %> + +<h3><%=l(:label_ssamr_institution)%></h3> +<%= h @institution_name %> + + <% unless @memberships.empty? %> <h3><%=l(:label_project_plural)%></h3> <ul>
--- a/app/views/welcome/index.rhtml Mon Jun 06 14:24:13 2011 +0100 +++ b/app/views/welcome/index.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -1,7 +1,14 @@ -<h2><%= l(:label_home) %></h2> +<% if not Setting.notifications_text.empty? %> + <div class="notifications flash error"> + <%= textilizable Setting.notifications_text %> + </div> +<% end %> + +<h2><%= l(:label_home_heading) %></h2> <div class="splitcontentleft"> <%= textilizable Setting.welcome_text %> + <% if @news.any? %> <div class="news box"> <h3><%=l(:label_news_latest)%></h3> @@ -13,6 +20,13 @@ </div> <div class="splitcontentright"> + <% if not @tipsoftheday.empty? %> + <div class="newsoftheday box"> + <h3><%=l(:label_tipoftheday)%></h3> + <%= textilizable @tipsoftheday %> + </div> + <% end %> + <% if @projects.any? %> <div class="projects box"> <h3><%=l(:label_project_latest)%></h3>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config/initializers/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,41 @@ +K 25 +svn:wc:ra_dav:version-url +V 44 +/svn/!svn/ver/4904/trunk/config/initializers +END +inflections.rb +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/2895/trunk/config/initializers/inflections.rb +END +30-redmine.rb +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/4679/trunk/config/initializers/30-redmine.rb +END +10-patches.rb +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/4904/trunk/config/initializers/10-patches.rb +END +backtrace_silencers.rb +K 25 +svn:wc:ra_dav:version-url +V 67 +/svn/!svn/ver/2895/trunk/config/initializers/backtrace_silencers.rb +END +20-mime_types.rb +K 25 +svn:wc:ra_dav:version-url +V 61 +/svn/!svn/ver/1797/trunk/config/initializers/20-mime_types.rb +END +bigdecimal-segfault-fix.rb +K 25 +svn:wc:ra_dav:version-url +V 71 +/svn/!svn/ver/2895/trunk/config/initializers/bigdecimal-segfault-fix.rb +END
--- a/config/locales/bg.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/bg.yml Mon Jun 06 14:41:04 2011 +0100 @@ -501,6 +501,7 @@ label_login_with_open_id_option: или вход чрез OpenID label_password_lost: Забравена парола label_home: Начало + label_home_heading: Начало label_my_page: Лична страница label_my_account: Профил label_my_projects: Проекти, в които участвам
--- a/config/locales/bs.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/bs.yml Mon Jun 06 14:41:04 2011 +0100 @@ -441,6 +441,7 @@ label_login_with_open_id_option: ili prijava sa OpenID-om label_password_lost: Izgubljena lozinka label_home: Početna stranica + label_home_heading: Početna stranica label_my_page: Moja stranica label_my_account: Moj korisnički račun label_my_projects: Moji projekti
--- a/config/locales/ca.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/ca.yml Mon Jun 06 14:41:04 2011 +0100 @@ -477,6 +477,7 @@ label_login_with_open_id_option: "o entra amb l'OpenID" label_password_lost: Contrasenya perduda label_home: Inici + label_home_heading: Inici label_my_page: La meva pàgina label_my_account: El meu compte label_my_projects: Els meus projectes
--- a/config/locales/cs.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/cs.yml Mon Jun 06 14:41:04 2011 +0100 @@ -489,6 +489,7 @@ label_login_with_open_id_option: nebo se přihlašte s OpenID label_password_lost: Zapomenuté heslo label_home: Úvodní + label_home_heading: Úvodní label_my_page: Moje stránka label_my_account: Můj účet label_my_projects: Moje projekty
--- a/config/locales/da.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/da.yml Mon Jun 06 14:41:04 2011 +0100 @@ -368,6 +368,7 @@ label_register: Registrér label_password_lost: Glemt kodeord label_home: Forside + label_home_heading: Forside label_my_page: Min side label_my_account: Min konto label_my_projects: Mine projekter
--- a/config/locales/de.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/de.yml Mon Jun 06 14:41:04 2011 +0100 @@ -492,6 +492,7 @@ label_login_with_open_id_option: oder mit OpenID anmelden label_password_lost: Kennwort vergessen label_home: Hauptseite + label_home_heading: Hauptseite label_my_page: Meine Seite label_my_account: Mein Konto label_my_projects: Meine Projekte
--- a/config/locales/el.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/el.yml Mon Jun 06 14:41:04 2011 +0100 @@ -439,6 +439,7 @@ label_login_with_open_id_option: ή συνδεθείτε με OpenID label_password_lost: Ανάκτηση κωδικού πρόσβασης label_home: Αρχική σελίδα + label_home_heading: Αρχική σελίδα label_my_page: Η σελίδα μου label_my_account: Ο λογαριασμός μου label_my_projects: Τα έργα μου
--- a/config/locales/en-GB.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/en-GB.yml Mon Jun 06 14:41:04 2011 +0100 @@ -131,6 +131,7 @@ not_same_project: "doesn't belong to the same project" circular_dependency: "This relation would create a circular dependency" cant_link_an_issue_with_a_descendant: "An issue cannot be linked to one of its subtasks" + must_accept_terms_and_conditions: "You must accept the Terms and Conditions" actionview_instancetag_blank_option: Please select @@ -213,6 +214,12 @@ gui_validation_error: 1 error gui_validation_error_plural: "%{count} errors" + field_ssamr_user_detail: + description: User Description + institution: Institution + + field_other_institution: '' + field_name: Name field_description: Description field_summary: Summary @@ -252,6 +259,7 @@ field_role: Role field_homepage: Homepage field_is_public: Public + field_is_private: Private field_parent: Subproject of field_is_in_roadmap: Issues displayed in roadmap field_login: Login @@ -402,8 +410,8 @@ permission_comment_news: Comment news permission_manage_documents: Manage documents permission_view_documents: View documents - permission_manage_files: Manage files - permission_view_files: View files + permission_manage_files: Manage downloads + permission_view_files: View downloads permission_manage_wiki: Manage wiki permission_rename_wiki_pages: Rename wiki pages permission_delete_wiki_pages: Delete wiki pages @@ -426,17 +434,25 @@ permission_export_wiki_pages: Export wiki pages permission_manage_subtasks: Manage subtasks - project_module_issue_tracking: Issue tracking + project_module_issue_tracking: Issue tracking (bugs and feature requests) project_module_time_tracking: Time tracking project_module_news: News project_module_documents: Documents - project_module_files: Files + project_module_files: Files for download project_module_wiki: Wiki - project_module_repository: Repository + project_module_repository: Source code repository project_module_boards: Forums project_module_calendar: Calendar project_module_gantt: Gantt + project_module_embedded: Embedded documentation (Javadoc or Doxygen) + label_tipoftheday: Tip of the day + label_notifications: Important Message + field_terms_and_conditions: 'Terms and Conditions:' + accept_terms_and_conditions: 'I have read and agree with the ' + label_ssamr_description: Research description + label_ssamr_details: Other Details + label_ssamr_institution: Institution label_user: User label_user_plural: Users label_user_new: New user @@ -444,12 +460,15 @@ label_project: Project label_project_new: New project label_project_plural: Projects + label_my_project_plural: My Projects + label_other_project_plural: Other Projects label_x_projects: zero: no projects one: 1 project other: "%{count} projects" label_project_all: All Projects label_project_latest: Latest projects + label_managers: Managed by label_issue: Issue label_issue_new: New issue label_issue_plural: Issues @@ -535,7 +554,7 @@ label_attachment: File label_attachment_new: New file label_attachment_delete: Delete file - label_attachment_plural: Files + label_attachment_plural: Downloads label_file_added: File added label_report: Report label_report_plural: Reports @@ -738,7 +757,7 @@ label_updated_time_by: "Updated by %{author} %{age} ago" label_updated_time: "Updated %{value} ago" label_jump_to_a_project: Jump to a project... - label_file_plural: Files + label_file_plural: Downloads label_changeset_plural: Changesets label_default_columns: Default columns label_no_change_option: (No change) @@ -882,6 +901,12 @@ text_caracters_maximum: "%{count} characters maximum." text_caracters_minimum: "Must be at least %{count} characters long." text_length_between: "Length between %{min} and %{max} characters." + text_project_identifier_info: 'Only lower case letters (a-z), numbers and dashes are allowed.<br /> This will be used in all project-related URLs, and as the repository name. Once saved, the identifier <b>can not</b> be changed.' + text_project_homepage_info: 'Link to an external project page.' + text_project_name_info: "This will be the name of your project throughout this site.<br /> You can change your project's name at any time, in the project's settings." + text_project_visibility_info: "If your project is not public, it will only be visible to users that you have added as project members." + text_user_ssamr_description_info: 'Please describe your current research or development interests, within the fields of audio and music.<br/>This information is publicly visible in your profile and you can edit it at any time.' + text_issue_parent_issue_info: 'If this is a subtask, please insert its parent task number or write the main task name.' text_tracker_no_workflow: No workflow defined for this tracker text_unallowed_characters: Unallowed characters text_comma_separated: Multiple values allowed (comma separated). @@ -920,6 +945,7 @@ text_wiki_page_destroy_children: "Delete child pages and all their descendants" text_wiki_page_reassign_children: "Reassign child pages to this parent page" text_own_membership_delete_confirmation: "You are about to remove some or all of your permissions and may no longer be able to edit this project after that.\nAre you sure you want to continue?" + text_settings_repo_creation: The repository for a project should be set up automatically within a few minutes of the project being created.<br>You should not have to adjust any settings here; please check again in ten minutes. text_zoom_in: Zoom in text_zoom_out: Zoom out text_warn_on_leaving_unsaved: "The current page contains unsaved text that will be lost if you leave this page." @@ -979,3 +1005,4 @@ label_git_report_last_commit: Report last commit for files and directories text_scm_config: You can configure your scm commands in config/configuration.yml. Please restart the application after editing it. text_scm_command_not_available: Scm command is not available. Please check settings on the administration panel. + label_principal_search: "Search by name:"
--- a/config/locales/en.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/en.yml Mon Jun 06 14:41:04 2011 +0100 @@ -89,7 +89,6 @@ gb: "GB" tb: "TB" - # Used in array.to_sentence. support: array: @@ -127,6 +126,7 @@ not_same_project: "doesn't belong to the same project" circular_dependency: "This relation would create a circular dependency" cant_link_an_issue_with_a_descendant: "An issue cannot be linked to one of its subtasks" + must_accept_terms_and_conditions: "You must accept the Terms and Conditions" actionview_instancetag_blank_option: Please select @@ -208,7 +208,13 @@ gui_validation_error: 1 error gui_validation_error_plural: "%{count} errors" - + + field_ssamr_user_detail: + description: User Description + institution: Institution + + field_other_institution: '' + field_name: Name field_description: Description field_summary: Summary @@ -248,6 +254,7 @@ field_role: Role field_homepage: Homepage field_is_public: Public + field_is_private: Private field_parent: Subproject of field_is_in_roadmap: Issues displayed in roadmap field_login: Login @@ -316,6 +323,8 @@ field_cvsroot: CVSROOT field_cvs_module: Module + field_terms_and_conditions: 'Terms and Conditions:' + accept_terms_and_conditions: 'I have read and agree with the ' setting_app_title: Application title setting_app_subtitle: Application subtitle setting_welcome_text: Welcome text @@ -408,8 +417,8 @@ permission_comment_news: Comment news permission_manage_documents: Manage documents permission_view_documents: View documents - permission_manage_files: Manage files - permission_view_files: View files + permission_manage_files: Manage Downloads + permission_view_files: View Downloads permission_manage_wiki: Manage wiki permission_rename_wiki_pages: Rename wiki pages permission_delete_wiki_pages: Delete wiki pages @@ -432,17 +441,21 @@ permission_export_wiki_pages: Export wiki pages permission_manage_subtasks: Manage subtasks - project_module_issue_tracking: Issue tracking + project_module_issue_tracking: Issue tracking (bugs and feature requests) project_module_time_tracking: Time tracking project_module_news: News project_module_documents: Documents - project_module_files: Files + project_module_files: Files for download project_module_wiki: Wiki - project_module_repository: Repository + project_module_repository: Source code repository project_module_boards: Forums project_module_calendar: Calendar - project_module_gantt: Gantt - + project_module_gantt: Gantt chart + project_module_embedded: Embedded documentation (Javadoc or Doxygen) + label_tipoftheday: Tip of the day + label_ssamr_details: Other Details + label_ssamr_institution: Institution + label_ssamr_description: Research description label_user: User label_user_plural: Users label_user_new: New user @@ -450,12 +463,15 @@ label_project: Project label_project_new: New project label_project_plural: Projects + label_my_project_plural: My Projects + label_other_project_plural: Other Projects label_x_projects: zero: no projects one: 1 project other: "%{count} projects" label_project_all: All Projects label_project_latest: Latest projects + label_managers: Managed by label_issue: Issue label_issue_new: New issue label_issue_plural: Issues @@ -501,6 +517,7 @@ label_login_with_open_id_option: or login with OpenID label_password_lost: Lost password label_home: Home + label_home_heading: Welcome! label_my_page: My page label_my_account: My account label_my_projects: My projects @@ -544,7 +561,7 @@ label_attachment: File label_attachment_new: New file label_attachment_delete: Delete file - label_attachment_plural: Files + label_attachment_plural: Downloads label_file_added: File added label_report: Report label_report_plural: Reports @@ -747,7 +764,7 @@ label_updated_time_by: "Updated by %{author} %{age} ago" label_updated_time: "Updated %{value} ago" label_jump_to_a_project: Jump to a project... - label_file_plural: Files + label_file_plural: Downloads label_changeset_plural: Changesets label_default_columns: Default columns label_no_change_option: (No change) @@ -812,7 +829,7 @@ label_profile: Profile label_subtask_plural: Subtasks label_project_copy_notifications: Send email notifications during the project copy - label_principal_search: "Search for user or group:" + label_principal_search: "Search by name:" label_user_search: "Search for user:" label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee @@ -898,6 +915,8 @@ text_caracters_maximum: "%{count} characters maximum." text_caracters_minimum: "Must be at least %{count} characters long." text_length_between: "Length between %{min} and %{max} characters." + text_issue_parent_issue_info: 'If this is a subtask, please insert its parent task number or write the main task name.' + text_user_ssamr_description_info: 'Please describe your current research or development interests, within the fields of audio and music.<br/>This information is publicly visible in your profile and you can edit it at any time.' text_tracker_no_workflow: No workflow defined for this tracker text_unallowed_characters: Unallowed characters text_comma_separated: Multiple values allowed (comma separated). @@ -941,6 +960,7 @@ text_zoom_in: Zoom in text_zoom_out: Zoom out text_warn_on_leaving_unsaved: "The current page contains unsaved text that will be lost if you leave this page." + text_settings_repo_creation: The repository for a project should be set up automatically within a few minutes of the project being created.<br>You should not have to adjust any settings here.<br>Please check again in ten minutes, and <a href="/projects/soundsoftware-site/wiki/Help">contact us</a> if there is any problem. text_scm_path_encoding_note: "Default: UTF-8" text_git_repository_note: "Bare and local repository (e.g. /gitrepo, c:\gitrepo)" text_mercurial_repository_note: "Local repository (e.g. /hgrepo, c:\hgrepo)"
--- a/config/locales/es.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/es.yml Mon Jun 06 14:41:04 2011 +0100 @@ -464,6 +464,7 @@ label_help: Ayuda label_history: Histórico label_home: Inicio + label_home_heading: Inicio label_in: en label_in_less_than: en menos que label_in_more_than: en más que
--- a/config/locales/eu.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/eu.yml Mon Jun 06 14:41:04 2011 +0100 @@ -462,6 +462,7 @@ label_login_with_open_id_option: edo OpenID-rekin saioa hasi label_password_lost: Pasahitza galduta label_home: Hasiera + label_home_heading: Hasiera label_my_page: Nire orria label_my_account: Nire kontua label_my_projects: Nire proiektuak
--- a/config/locales/fi.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/fi.yml Mon Jun 06 14:41:04 2011 +0100 @@ -364,6 +364,7 @@ label_register: Rekisteröidy label_password_lost: Hukattu salasana label_home: Koti + label_home_heading: Koti label_my_page: Omasivu label_my_account: Oma tili label_my_projects: Omat projektit
--- a/config/locales/fr.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/fr.yml Mon Jun 06 14:41:04 2011 +0100 @@ -496,6 +496,7 @@ label_login_with_open_id_option: S'authentifier avec OpenID label_password_lost: Mot de passe perdu label_home: Accueil + label_home_heading: Accueil label_my_page: Ma page label_my_account: Mon compte label_my_projects: Mes projets
--- a/config/locales/gl.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/gl.yml Mon Jun 06 14:41:04 2011 +0100 @@ -441,6 +441,7 @@ label_help: Axuda label_history: Histórico label_home: Inicio + label_home_heading: Inicio label_in: en label_in_less_than: en menos que label_in_more_than: en mais que
--- a/config/locales/he.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/he.yml Mon Jun 06 14:41:04 2011 +0100 @@ -481,6 +481,7 @@ label_login_with_open_id_option: או התחבר באמצעות OpenID label_password_lost: אבדה הסיסמה? label_home: דף הבית + label_home_heading: דף הבית label_my_page: הדף שלי label_my_account: החשבון שלי label_my_projects: הפרויקטים שלי
--- a/config/locales/hr.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/hr.yml Mon Jun 06 14:41:04 2011 +0100 @@ -457,6 +457,7 @@ label_login_with_open_id_option: or login with OpenID label_password_lost: Izgubljena zaporka label_home: Početna stranica + label_home_heading: Početna stranica label_my_page: Moja stranica label_my_account: Moj profil label_my_projects: Moji projekti
--- a/config/locales/hu.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/hu.yml Mon Jun 06 14:41:04 2011 +0100 @@ -380,6 +380,7 @@ label_register: Regisztráljon label_password_lost: Elfelejtett jelszó label_home: Kezdőlap + label_home_heading: Kezdőlap label_my_page: Saját kezdőlapom label_my_account: Fiókom adatai label_my_projects: Saját projektem
--- a/config/locales/id.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/id.yml Mon Jun 06 14:41:04 2011 +0100 @@ -448,6 +448,7 @@ label_login_with_open_id_option: atau login menggunakan OpenID label_password_lost: Lupa password label_home: Halaman depan + label_home_heading: Halaman depan label_my_page: Beranda label_my_account: Akun saya label_my_projects: Proyek saya
--- a/config/locales/it.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/it.yml Mon Jun 06 14:41:04 2011 +0100 @@ -324,6 +324,7 @@ label_register: Registrati label_password_lost: Password dimenticata label_home: Home + label_home_heading: Home label_my_page: Pagina personale label_my_account: Il mio utente label_my_projects: I miei progetti
--- a/config/locales/ja.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/ja.yml Mon Jun 06 14:41:04 2011 +0100 @@ -514,6 +514,7 @@ label_login_with_open_id_option: またはOpenIDでログインする label_password_lost: パスワードの再発行 label_home: ホーム + label_home_heading: ホーム label_my_page: マイページ label_my_account: 個人設定 label_my_projects: マイプロジェクト
--- a/config/locales/ko.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/ko.yml Mon Jun 06 14:41:04 2011 +0100 @@ -487,6 +487,7 @@ label_login_with_open_id_option: 또는 OpenID로 로그인 label_password_lost: 비밀번호 찾기 label_home: 초기화면 + label_home_heading: 초기화면 label_my_page: 내 페이지 label_my_account: 내 계정 label_my_projects: 내 프로젝트
--- a/config/locales/lt.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/lt.yml Mon Jun 06 14:41:04 2011 +0100 @@ -503,6 +503,7 @@ label_register: Užsiregistruoti label_password_lost: Prarastas slaptažodis label_home: Pagrindinis + label_home_heading: Pagrindinis label_my_page: Mano puslapis label_my_account: Mano paskyra label_my_projects: Mano projektai
--- a/config/locales/lv.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/lv.yml Mon Jun 06 14:41:04 2011 +0100 @@ -456,6 +456,7 @@ label_login_with_open_id_option: vai pieslēgties ar OpenID label_password_lost: Nozaudēta parole label_home: Sākums + label_home_heading: Sākums label_my_page: Mana lapa label_my_account: Mans konts label_my_projects: Mani projekti
--- a/config/locales/mk.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/mk.yml Mon Jun 06 14:41:04 2011 +0100 @@ -474,6 +474,7 @@ label_login_with_open_id_option: или најави се со OpenID label_password_lost: Изгубена лозинка label_home: Почетна + label_home_heading: Почетна label_my_page: Мојата страна label_my_account: Мојот профил label_my_projects: Мои проекти
--- a/config/locales/mn.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/mn.yml Mon Jun 06 14:41:04 2011 +0100 @@ -460,6 +460,7 @@ label_login_with_open_id_option: or login with OpenID label_password_lost: Нууц үгээ алдсан label_home: Нүүр + label_home_heading: Нүүр label_my_page: Миний хуудас label_my_account: Миний данс label_my_projects: Миний төслүүд
--- a/config/locales/nl.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/nl.yml Mon Jun 06 14:41:04 2011 +0100 @@ -411,6 +411,7 @@ label_help: Help label_history: Geschiedenis label_home: Home + label_home_heading: Home label_in: in label_in_less_than: in minder dan label_in_more_than: in meer dan
--- a/config/locales/no.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/no.yml Mon Jun 06 14:41:04 2011 +0100 @@ -351,6 +351,7 @@ label_register: Registrer label_password_lost: Mistet passord label_home: Hjem + label_home_heading: Hjem label_my_page: Min side label_my_account: Min konto label_my_projects: Mine prosjekter
--- a/config/locales/pl.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/pl.yml Mon Jun 06 14:41:04 2011 +0100 @@ -438,6 +438,7 @@ label_help: Pomoc label_history: Historia label_home: Główna + label_home_heading: Główna label_in: w label_in_less_than: mniejsze niż label_in_more_than: większe niż
--- a/config/locales/pt-BR.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/pt-BR.yml Mon Jun 06 14:41:04 2011 +0100 @@ -391,6 +391,7 @@ label_register: Cadastre-se label_password_lost: Perdi minha senha label_home: Página inicial + label_home_heading: Página inicial label_my_page: Minha página label_my_account: Minha conta label_my_projects: Meus projetos
--- a/config/locales/pt.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/pt.yml Mon Jun 06 14:41:04 2011 +0100 @@ -374,6 +374,7 @@ label_register: Registar label_password_lost: Perdi a palavra-chave label_home: Página Inicial + label_home_heading: Página Inicial label_my_page: Página Pessoal label_my_account: Minha conta label_my_projects: Meus projectos
--- a/config/locales/ro.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/ro.yml Mon Jun 06 14:41:04 2011 +0100 @@ -420,6 +420,7 @@ label_login_with_open_id_option: sau autentificare cu OpenID label_password_lost: Parolă uitată label_home: Acasă + label_home_heading: Acasă label_my_page: Pagina mea label_my_account: Contul meu label_my_projects: Proiectele mele
--- a/config/locales/ru.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/ru.yml Mon Jun 06 14:41:04 2011 +0100 @@ -519,6 +519,7 @@ label_help: Помощь label_history: История label_home: Домашняя страница + label_home_heading: Домашняя страница label_incoming_emails: Приём сообщений label_index_by_date: История страниц label_index_by_title: Оглавление
--- a/config/locales/sk.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/sk.yml Mon Jun 06 14:41:04 2011 +0100 @@ -354,6 +354,7 @@ label_register: Registrovať label_password_lost: Zabudnuté heslo label_home: Domovská stránka + label_home_heading: Domovská stránka label_my_page: Moja stránka label_my_account: Môj účet label_my_projects: Moje projekty
--- a/config/locales/sl.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/sl.yml Mon Jun 06 14:41:04 2011 +0100 @@ -416,6 +416,7 @@ label_register: Registracija label_password_lost: Izgubljeno geslo label_home: Domov + label_home_heading: Domov label_my_page: Moja stran label_my_account: Moj račun label_my_projects: Moji projekti
--- a/config/locales/sr-YU.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/sr-YU.yml Mon Jun 06 14:41:04 2011 +0100 @@ -471,6 +471,7 @@ label_login_with_open_id_option: ili prijava sa OpenID label_password_lost: Izgubljena lozinka label_home: Početak + label_home_heading: Početak label_my_page: Moja stranica label_my_account: Moj nalog label_my_projects: Moji projekti
--- a/config/locales/sr.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/sr.yml Mon Jun 06 14:41:04 2011 +0100 @@ -471,6 +471,7 @@ label_login_with_open_id_option: или пријава са OpenID label_password_lost: Изгубљена лозинка label_home: Почетак + label_home_heading: Почетак label_my_page: Моја страница label_my_account: Мој налог label_my_projects: Моји пројекти
--- a/config/locales/sv.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/sv.yml Mon Jun 06 14:41:04 2011 +0100 @@ -537,6 +537,7 @@ label_login_with_open_id_option: eller logga in med OpenID label_password_lost: Glömt lösenord label_home: Hem + label_home_heading: Hem label_my_page: Min sida label_my_account: Mitt konto label_my_projects: Mina projekt
--- a/config/locales/th.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/th.yml Mon Jun 06 14:41:04 2011 +0100 @@ -356,6 +356,7 @@ label_register: ลงทะเบียน label_password_lost: ลืมรหัสผ่าน label_home: หน้าแรก + label_home_heading: หน้าแรก label_my_page: หน้าของฉัน label_my_account: บัญชีของฉัน label_my_projects: โครงการของฉัน
--- a/config/locales/tr.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/tr.yml Mon Jun 06 14:41:04 2011 +0100 @@ -380,6 +380,7 @@ label_register: Kayıt label_password_lost: Parolamı unuttum label_home: Anasayfa + label_home_heading: Anasayfa label_my_page: Kişisel Sayfam label_my_account: Hesabım label_my_projects: Projelerim
--- a/config/locales/uk.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/uk.yml Mon Jun 06 14:41:04 2011 +0100 @@ -331,6 +331,7 @@ label_register: Зареєструватися label_password_lost: Забули пароль label_home: Домашня сторінка + label_home_heading: Домашня сторінка label_my_page: Моя сторінка label_my_account: Мій обліковий запис label_my_projects: Мої проекти
--- a/config/locales/vi.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/vi.yml Mon Jun 06 14:41:04 2011 +0100 @@ -418,6 +418,7 @@ label_register: Đăng ký label_password_lost: Phục hồi mật mã label_home: Trang chính + label_home_heading: Trang chính label_my_page: Trang riêng label_my_account: Cá nhân label_my_projects: Dự án của bạn
--- a/config/locales/zh-TW.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/zh-TW.yml Mon Jun 06 14:41:04 2011 +0100 @@ -583,6 +583,7 @@ label_login_with_open_id_option: 或使用 OpenID 登入 label_password_lost: 遺失密碼 label_home: 網站首頁 + label_home_heading: 網站首頁 label_my_page: 帳戶首頁 label_my_account: 我的帳戶 label_my_projects: 我的專案
--- a/config/locales/zh.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/locales/zh.yml Mon Jun 06 14:41:04 2011 +0100 @@ -487,6 +487,7 @@ label_login_with_open_id_option: 或使用OpenID登录 label_password_lost: 忘记密码 label_home: 主页 + label_home_heading: 主页 label_my_page: 我的工作台 label_my_account: 我的帐号 label_my_projects: 我的项目
--- a/config/routes.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/config/routes.rb Mon Jun 06 14:41:04 2011 +0100 @@ -250,6 +250,7 @@ map.with_options :controller => 'sys' do |sys| sys.connect 'sys/projects.:format', :action => 'projects', :conditions => {:method => :get} sys.connect 'sys/projects/:id/repository.:format', :action => 'create_project_repository', :conditions => {:method => :post} + sys.connect 'sys/projects/:id/embedded.:format', :action => 'set_embedded_active', :conditions => { :method => :post } end # Install the default route as the lowest priority.
--- a/config/settings.yml Mon Jun 06 14:24:13 2011 +0100 +++ b/config/settings.yml Mon Jun 06 14:41:04 2011 +0100 @@ -25,6 +25,10 @@ default: Project management welcome_text: default: +tipoftheday_text: + default: +notifications_text: + default: login_required: default: 0 self_registration:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/db/seeds.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,9 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). +# +# Examples: +# +# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) +# Major.create(:name => 'Daley', :city => cities.first) + +puts "this is a test" \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/db/migrate/20101123161346_create_ssamr_user_details.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,14 @@ +class CreateSsamrUserDetails < ActiveRecord::Migration + def self.up + create_table :ssamr_user_details do |t| + t.integer :user_id + t.text :description + t.text :university + end + end + + def self.down + drop_table :ssamr_user_details + end + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/db/migrate/20101216140621_create_institutions.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,13 @@ +class CreateInstitutions < ActiveRecord::Migration + def self.up + create_table :institutions do |t| + t.string :name + + t.timestamps + end + end + + def self.down + drop_table :institutions + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/db/migrate/20101216145813_fix_university_name_in_ssamr_details_table.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,10 @@ +class FixUniversityNameInSsamrDetailsTable < ActiveRecord::Migration + def self.up + rename_column :ssamr_user_details, :university, :institution_id + end + + def self.down + # there's no need to rollback the name of this column + # because it was not used previously + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/db/migrate/20110126153504_add_other_institution_column_to_ssamr_user_details.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,9 @@ +class AddOtherInstitutionColumnToSsamrUserDetails < ActiveRecord::Migration + def self.up + add_column :ssamr_user_details, :other_institution, :string + end + + def self.down + remove_column :ssamr_user_details, :other_institution + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/db/migrate/20110127161758_add_institution_type_column_to_ssamr_user_details.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,9 @@ +class AddInstitutionTypeColumnToSsamrUserDetails < ActiveRecord::Migration + def self.up + add_column :ssamr_user_details, :institution_type, :boolean + end + + def self.down + remove_column :ssamr_user_details, :institution_type + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/db/migrate/20110202170156_add_order_column_to_institutions.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,9 @@ +class AddOrderColumnToInstitutions < ActiveRecord::Migration + def self.up + add_column :institutions, :order, :integer + end + + def self.down + remove_column :institutions, :order + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/db/seed_data/institutions.txt Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,141 @@ +University of Aberdeen|1 +University of Abertay Dundee |2 +Aberystwyth University|3 +Anglia Ruskin University|4 +University of the Arts London|5 +Aston University|6 +Bangor University|7 +University of Bath|8 +Bath Spa University|9 +University of Bedfordshire|10 +Birkbeck, University of London|11 +University of Birmingham|12 +Birmingham City University|13 +Birmingham Conservatoire|14 +University Centre at Blackburn College|15 +University of Bolton|16 +Bournemouth University|17 +University of Bradford|18 +University of Brighton|19 +University of Bristol|20 +Brunel University|21 +University of Buckingham|22 +Buckinghamshire New University|23 +University of Cambridge|24 +Institute of Cancer Research, University of London|25 +Canterbury Christ Church University|26 +Cardiff University|27 +University of Central Lancashire|28 +Central School of Speech and Drama, University of London|29 +University of Chester|30 +University of Chichester|31 +City University London|32 +Courtauld Institute of Art|33 +Coventry University|34 +Cranfield University|35 +University for the Creative Arts|36 +University of Cumbria|37 +De Montfort University|38 +University of Derby|39 +University of Dundee|40 +Durham University|41 +University of East Anglia|42 +University of East London|43 +Edge Hill University|44 +University of Edinburgh|45 +Edinburgh Napier University|46 +Institute of Education, University of London|47 +University of Essex|48 +University of Exeter|49 +University of Glamorgan|50 +University of Glasgow|51 +Glasgow Caledonian University|52 +University of Gloucestershire|53 +Goldsmiths, University of London|54 +University of Greenwich|55 +Glyndŵr University|56 +Heriot-Watt University|57 +University of Hertfordshire|58 +Heythrop College|59 +University of Huddersfield|60 +University of Hull|61 +Hull York Medical School|62 +Imperial College London|63 +Keele University|64 +University of Kent|65 +King's College London|66 +Kingston University|67 +Lancaster University|68 +University of Leeds|69 +Leeds Metropolitan University|70 +University of Leicester|71 +University of Lincoln|72 +University of Liverpool|73 +Liverpool Hope University|74 +Liverpool John Moores University|75 +London Business School|76 +London College of Music|77 +London Metropolitan University|78 +London School of Economics and Political Science|79 +London School of Hygiene and Tropical Medicine|80 +London South Bank University|81 +Loughborough University|82 +University of Manchester|83 +Manchester Metropolitan University|84 +Middlesex University|85 +Newcastle University|86 +University of Northampton|87 +Northumbria University|88 +University of Nottingham|89 +Nottingham Trent University|90 +The Open University|91 +University of Oxford|92 +Oxford Brookes University|93 +Peninsula College of Medicine and Dentistry|94 +University of Plymouth|95 +University of Portsmouth|96 +Queen's University Belfast|97 +Queen Margaret University|98 +Queen Mary, University of London|99 +University of Reading|100 +The Robert Gordon University, Aberdeen|101 +Roehampton University|102 +Royal Academy of Music|103 +Royal College of Art|104 +Royal Holloway, University of London|105 +Royal Veterinary College|106 +University of St Andrews|107 +St George's, University of London|108 +University of Salford|109 +School of Advanced Study, University of London|110 +School of Oriental and African Studies|111 +School of Pharmacy, University of London|112 +University of Sheffield|113 +Sheffield Hallam University|114 +University of Southampton|115 +Southampton Solent University|116 +Staffordshire University|117 +University of Stirling|118 +University of Strathclyde|119 +University of Sunderland|120 +University of Surrey|121 +University of Sussex|122 +Swansea Metropolitan University|123 +Swansea University|124 +University of Teesside|125 +Thames Valley University|126 +University of Ulster|127 +University College London|128 +University of Wales|129 +University of Wales Institute, Cardiff|130 +University of Wales, Newport|131 +University of Wales, Trinity Saint David|132 +University of Warwick|133 +University of Westminster|134 +University of the West of England|135 +University of the West of Scotland|136 +University of Winchester|137 +University of Wolverhampton|138 +University of Worcester|139 +University of York|140 +York St John University|141
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/db/seeds.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,27 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). +# +# Examples: +# +# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) +# Major.create(:name => 'Daley', :city => cities.first) + +def truncate_table(table_name) + quoted = connection.quote_table_name(table_name) + connection.execute("TRUNCATE #{quoted}") +end + +def connection + ActiveRecord::Base.connection +end + +truncate_table('institutions') + +open("db/seed_data/institutions.txt") do |institutions| + institutions.read.each_line do |institution| + inst=institution.split('|') + + + Institution.create(:name => inst[0].chomp, :order => inst[1].chomp) + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/mercurial/redminehelper.py Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,91 @@ +# redminehelper: Redmine helper extension for Mercurial +# it's a draft to show a possible way to explore repository by the Redmine overhaul patch +# see: http://www.redmine.org/issues/4455 +# +# Copyright 2010 Alessio Franceschelli (alefranz.net) +# Copyright 2010 Yuya Nishihara <yuya@tcha.org> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +'''command to list revision of each file +''' + +import re, time +from mercurial import cmdutil, commands, node, error + +SPECIAL_TAGS = ('tip',) + +def rhsummary(ui, repo, **opts): + """output the summary of the repository""" + # see mercurial/commands.py:tip + ui.write(':tip: rev node\n') + tipctx = repo[len(repo) - 1] + ui.write('%d %s\n' % (tipctx.rev(), tipctx)) + + # see mercurial/commands.py:root + ui.write(':root: path\n') + ui.write(repo.root + '\n') + + # see mercurial/commands.py:tags + ui.write(':tags: rev node name\n') + for t, n in reversed(repo.tagslist()): + if t in SPECIAL_TAGS: + continue + try: + r = repo.changelog.rev(n) + except error.LookupError: + r = -1 + ui.write('%d %s %s\n' % (r, node.short(n), t)) + + # see mercurial/commands.py:branches + def iterbranches(): + for t, n in repo.branchtags().iteritems(): + yield t, n, repo.changelog.rev(n) + + ui.write(':branches: rev node name\n') + for t, n, r in sorted(iterbranches(), key=lambda e: e[2], reverse=True): + if repo.lookup(r) in repo.branchheads(t, closed=False): + ui.write('%d %s %s\n' % (r, node.short(n), t)) # only open branch + +def rhentries(ui, repo, path='', **opts): + """output the entries of the specified directory""" + rev = opts.get('rev') + pathprefix = (path.rstrip('/') + '/').lstrip('/') + + # TODO: clean up + dirs, files = {}, {} + mf = repo[rev].manifest() + for f in repo[rev]: + if not f.startswith(pathprefix): + continue + + name = re.sub(r'/.*', '', f[len(pathprefix):]) + if '/' in f[len(pathprefix):]: + dirs[name] = (name,) + else: + try: + fctx = repo.filectx(f, fileid=mf[f]) + ctx = fctx.changectx() + tm, tzoffset = ctx.date() + localtime = int(tm) + tzoffset - time.timezone + files[name] = (ctx.rev(), node.short(ctx.node()), localtime, + fctx.size(), name) + except LookupError: # TODO: when this occurs? + pass + + ui.write(':dirs: name\n') + for n, v in sorted(dirs.iteritems(), key=lambda e: e[0]): + ui.write(' '.join(v) + '\n') + + ui.write(':files: rev node time size name\n') + for n, v in sorted(files.iteritems(), key=lambda e: e[0]): + ui.write(' '.join(str(e) for e in v) + '\n') + + +cmdtable = { + 'rhsummary': (rhsummary, [], 'hg rhsummary'), + 'rhentries': (rhentries, + [('r', 'rev', '', 'show the specified revision')], + 'hg rhentries [path]'), +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/soundsoftware/SoundSoftware.pm Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,433 @@ +package Apache::Authn::SoundSoftware; + +=head1 Apache::Authn::SoundSoftware + +SoundSoftware - a mod_perl module for Apache authentication against a +Redmine database and optional LDAP implementing the access control +rules required for the SoundSoftware.ac.uk repository site. + +=head1 SYNOPSIS + +This module is closely based on the Redmine.pm authentication module +provided with Redmine. It is intended to be used for authentication +in front of a repository service such as hgwebdir. + +Requirements: + +1. Clone/pull from repo for public project: Any user, no +authentication required + +2. Clone/pull from repo for private project: Project members only + +3. Push to repo for public project: "Permitted" users only (this +probably means project members who are also identified in the hgrc web +section for the repository and so will be approved by hgwebdir?) + +4. Push to repo for private project: "Permitted" users only (as above) + +=head1 INSTALLATION + +Debian/ubuntu: + + apt-get install libapache-dbi-perl libapache2-mod-perl2 \ + libdbd-mysql-perl libauthen-simple-ldap-perl libio-socket-ssl-perl + +Note that LDAP support is hardcoded "on" in this script (it is +optional in the original Redmine.pm). + +=head1 CONFIGURATION + + ## This module has to be in your perl path + ## eg: /usr/local/lib/site_perl/Apache/Authn/SoundSoftware.pm + PerlLoadModule Apache::Authn::SoundSoftware + + # Example when using hgwebdir + ScriptAlias / "/var/hg/hgwebdir.cgi/" + + <Location /> + AuthName "Mercurial" + AuthType Basic + Require valid-user + PerlAccessHandler Apache::Authn::SoundSoftware::access_handler + PerlAuthenHandler Apache::Authn::SoundSoftware::authen_handler + SoundSoftwareDSN "DBI:mysql:database=redmine;host=localhost" + SoundSoftwareDbUser "redmine" + SoundSoftwareDbPass "password" + Options +ExecCGI + AddHandler cgi-script .cgi + ## Optional where clause (fulltext search would be slow and + ## database dependant). + # SoundSoftwareDbWhereClause "and members.role_id IN (1,2)" + ## Optional prefix for local repository URLs + # SoundSoftwareRepoPrefix "/var/hg/" + </Location> + +See the original Redmine.pm for further configuration notes. + +=cut + +use strict; +use warnings FATAL => 'all', NONFATAL => 'redefine'; + +use DBI; +use Digest::SHA1; +use Authen::Simple::LDAP; +use Apache2::Module; +use Apache2::Access; +use Apache2::ServerRec qw(); +use Apache2::RequestRec qw(); +use Apache2::RequestUtil qw(); +use Apache2::Const qw(:common :override :cmd_how); +use APR::Pool (); +use APR::Table (); + +my @directives = ( + { + name => 'SoundSoftwareDSN', + req_override => OR_AUTHCFG, + args_how => TAKE1, + errmsg => 'Dsn in format used by Perl DBI. eg: "DBI:Pg:dbname=databasename;host=my.db.server"', + }, + { + name => 'SoundSoftwareDbUser', + req_override => OR_AUTHCFG, + args_how => TAKE1, + }, + { + name => 'SoundSoftwareDbPass', + req_override => OR_AUTHCFG, + args_how => TAKE1, + }, + { + name => 'SoundSoftwareDbWhereClause', + req_override => OR_AUTHCFG, + args_how => TAKE1, + }, + { + name => 'SoundSoftwareRepoPrefix', + req_override => OR_AUTHCFG, + args_how => TAKE1, + }, +); + +sub SoundSoftwareDSN { + my ($self, $parms, $arg) = @_; + $self->{SoundSoftwareDSN} = $arg; + my $query = "SELECT + hashed_password, auth_source_id, permissions + FROM members, projects, users, roles, member_roles + WHERE + projects.id=members.project_id + AND member_roles.member_id=members.id + AND users.id=members.user_id + AND roles.id=member_roles.role_id + AND users.status=1 + AND login=? + AND identifier=? "; + $self->{SoundSoftwareQuery} = trim($query); +} + +sub SoundSoftwareDbUser { set_val('SoundSoftwareDbUser', @_); } +sub SoundSoftwareDbPass { set_val('SoundSoftwareDbPass', @_); } +sub SoundSoftwareDbWhereClause { + my ($self, $parms, $arg) = @_; + $self->{SoundSoftwareQuery} = trim($self->{SoundSoftwareQuery}.($arg ? $arg : "")." "); +} + +sub SoundSoftwareRepoPrefix { + my ($self, $parms, $arg) = @_; + if ($arg) { + $self->{SoundSoftwareRepoPrefix} = $arg; + } +} + +sub trim { + my $string = shift; + $string =~ s/\s{2,}/ /g; + return $string; +} + +sub set_val { + my ($key, $self, $parms, $arg) = @_; + $self->{$key} = $arg; +} + +Apache2::Module::add(__PACKAGE__, \@directives); + + +my %read_only_methods = map { $_ => 1 } qw/GET PROPFIND REPORT OPTIONS/; + +sub access_handler { + my $r = shift; + + print STDERR "SoundSoftware.pm: In access handler at " . scalar localtime() . "\n"; + + unless ($r->some_auth_required) { + $r->log_reason("No authentication has been configured"); + return FORBIDDEN; + } + + my $method = $r->method; + + print STDERR "SoundSoftware.pm: Method: $method, uri " . $r->uri . ", location " . $r->location . "\n"; + print STDERR "SoundSoftware.pm: Accept: " . $r->headers_in->{Accept} . "\n"; + + if (!defined $read_only_methods{$method}) { + print STDERR "SoundSoftware.pm: Method is not read-only, authentication handler required\n"; + return OK; + } + + my $dbh = connect_database($r); + unless ($dbh) { + print STDERR "SoundSoftware.pm: Database connection failed!: " . $DBI::errstr . "\n"; + return FORBIDDEN; + } + + +print STDERR "Connected to db, dbh is " . $dbh . "\n"; + + my $project_id = get_project_identifier($dbh, $r); + my $status = get_project_status($dbh, $project_id, $r); + + $dbh->disconnect(); + undef $dbh; + + if ($status == 0) { # nonexistent + print STDERR "SoundSoftware.pm: Project does not exist, refusing access\n"; + return FORBIDDEN; + } elsif ($status == 1) { # public + print STDERR "SoundSoftware.pm: Project is public, no restriction here\n"; + $r->set_handlers(PerlAuthenHandler => [\&OK]) + } else { # private + print STDERR "SoundSoftware.pm: Project is private, authentication handler required\n"; + } + + return OK +} + +sub authen_handler { + my $r = shift; + + print STDERR "SoundSoftware.pm: In authentication handler at " . scalar localtime() . "\n"; + + my $dbh = connect_database($r); + unless ($dbh) { + print STDERR "SoundSoftware.pm: Database connection failed!: " . $DBI::errstr . "\n"; + return AUTH_REQUIRED; + } + + my $project_id = get_project_identifier($dbh, $r); + my $realm = get_realm($dbh, $project_id, $r); + $r->auth_name($realm); + + my ($res, $redmine_pass) = $r->get_basic_auth_pw(); + unless ($res == OK) { + $dbh->disconnect(); + undef $dbh; + return $res; + } + + print STDERR "SoundSoftware.pm: User is " . $r->user . ", got password\n"; + + my $permitted = is_permitted($dbh, $project_id, $r->user, $redmine_pass, $r); + + $dbh->disconnect(); + undef $dbh; + + if ($permitted) { + return OK; + } else { + print STDERR "SoundSoftware.pm: Not permitted\n"; + $r->note_auth_failure(); + return AUTH_REQUIRED; + } +} + +sub get_project_status { + my $dbh = shift; + my $project_id = shift; + my $r = shift; + + if (!defined $project_id or $project_id eq '') { + return 0; # nonexistent + } + + my $sth = $dbh->prepare( + "SELECT is_public FROM projects WHERE projects.identifier = ?;" + ); + + $sth->execute($project_id); + my $ret = 0; # nonexistent + if (my @row = $sth->fetchrow_array) { + if ($row[0] eq "1" || $row[0] eq "t") { + $ret = 1; # public + } else { + $ret = 2; # private + } + } + $sth->finish(); + undef $sth; + + $ret; +} + +sub is_permitted { + my $dbh = shift; + my $project_id = shift; + my $redmine_user = shift; + my $redmine_pass = shift; + my $r = shift; + + my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass); + + my $cfg = Apache2::Module::get_config + (__PACKAGE__, $r->server, $r->per_dir_config); + + my $query = $cfg->{SoundSoftwareQuery}; + my $sth = $dbh->prepare($query); + $sth->execute($redmine_user, $project_id); + + my $ret; + while (my ($hashed_password, $auth_source_id, $permissions) = $sth->fetchrow_array) { + + # Test permissions for this user before we verify credentials + # -- if the user is not permitted this action anyway, there's + # not much point in e.g. contacting the LDAP + + my $method = $r->method; + + if ((defined $read_only_methods{$method} && $permissions =~ /:browse_repository/) + || $permissions =~ /:commit_access/) { + + # User would be permitted this action, if their + # credentials checked out -- test those now + + print STDERR "SoundSoftware.pm: User $redmine_user has required role, checking credentials\n"; + + unless ($auth_source_id) { + if ($hashed_password eq $pass_digest) { + print STDERR "SoundSoftware.pm: User $redmine_user authenticated via password\n"; + $ret = 1; + last; + } + } else { + my $sthldap = $dbh->prepare( + "SELECT host,port,tls,account,account_password,base_dn,attr_login FROM auth_sources WHERE id = ?;" + ); + $sthldap->execute($auth_source_id); + while (my @rowldap = $sthldap->fetchrow_array) { + my $ldap = Authen::Simple::LDAP->new( + host => ($rowldap[2] eq "1" || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]" : $rowldap[0], + port => $rowldap[1], + basedn => $rowldap[5], + binddn => $rowldap[3] ? $rowldap[3] : "", + bindpw => $rowldap[4] ? $rowldap[4] : "", + filter => "(".$rowldap[6]."=%s)" + ); + if ($ldap->authenticate($redmine_user, $redmine_pass)) { + print STDERR "SoundSoftware.pm: User $redmine_user authenticated via LDAP\n"; + $ret = 1; + } + } + $sthldap->finish(); + undef $sthldap; + } + } else { + print STDERR "SoundSoftware.pm: User $redmine_user lacks required role for this project\n"; + } + } + + $sth->finish(); + undef $sth; + + $ret; +} + +sub get_project_identifier { + my $dbh = shift; + my $r = shift; + + my $location = $r->location; + my ($repo) = $r->uri =~ m{$location/*([^/]+)}; + + return $repo if (!$repo); + + $repo =~ s/[^a-zA-Z0-9\._-]//g; + + # The original Redmine.pm returns the string just calculated as + # the project identifier. That won't do for us -- we may have + # (and in fact already do have, in our test instance) projects + # whose repository names differ from the project identifiers. + + # This is a rather fundamental change because it means that almost + # every request needs more than one database query -- which + # prompts us to start passing around $dbh instead of connecting + # locally within each function as is done in Redmine.pm. + + my $sth = $dbh->prepare( + "SELECT projects.identifier FROM projects, repositories WHERE repositories.project_id = projects.id AND repositories.url LIKE ?;" + ); + + my $cfg = Apache2::Module::get_config + (__PACKAGE__, $r->server, $r->per_dir_config); + + my $prefix = $cfg->{SoundSoftwareRepoPrefix}; + if (!defined $prefix) { $prefix = '%/'; } + + my $identifier = ''; + + $sth->execute($prefix . $repo); + my $ret = 0; + if (my @row = $sth->fetchrow_array) { + $identifier = $row[0]; + } + $sth->finish(); + undef $sth; + + print STDERR "SoundSoftware.pm: Repository '$repo' belongs to project '$identifier'\n"; + + $identifier; +} + +sub get_realm { + my $dbh = shift; + my $project_id = shift; + my $r = shift; + + my $sth = $dbh->prepare( + "SELECT projects.name FROM projects WHERE projects.identifier = ?;" + ); + + my $name = $project_id; + + $sth->execute($project_id); + my $ret = 0; + if (my @row = $sth->fetchrow_array) { + $name = $row[0]; + } + $sth->finish(); + undef $sth; + + # be timid about characters not permitted in auth realm and revert + # to project identifier if any are found + if ($name =~ m/[^\w\d\s\._-]/) { + $name = $project_id; + } + + my $realm = '"Mercurial repository for ' . "'$name'" . '"'; + + $realm; +} + +sub connect_database { + my $r = shift; + + my $cfg = Apache2::Module::get_config + (__PACKAGE__, $r->server, $r->per_dir_config); + + return DBI->connect($cfg->{SoundSoftwareDSN}, + $cfg->{SoundSoftwareDbUser}, + $cfg->{SoundSoftwareDbPass}); +} + +1;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/soundsoftware/doxysafe.pl Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,220 @@ +#!/usr/bin/perl -w + +# Read a Doxyfile and print it out again to stdout, with only +# whitelisted keys in it and with some keys set to pre-fixed values. +# +# Note that OUTPUT_DIRECTORY is not included; it should be added by +# the caller + +use strict; + +my $txt = join "", <>; +$txt =~ s/^\s*#.*$//gm; +$txt =~ s/\\\n//gs; +$txt =~ s/\r//g; +$txt =~ s/\n\s*\n/\n/gs; + +my %fixed = ( + FULL_PATH_NAMES => "NO", + SYMBOL_CACHE_SIZE => 2, + EXCLUDE_SYMLINKS => "YES", + GENERATE_HTML => "YES", + PERL_PATH => "/usr/bin/perl", + HAVE_DOT => "YES", + HTML_OUTPUT => ".", + HTML_DYNAMIC_SECTIONS => "NO", + SEARCHENGINE => "NO", + DOT_FONTNAME => "FreeMono", + DOT_FONTSIZE => 10, + DOT_FONTPATH => "/usr/share/fonts/truetype/freefont", + DOT_IMAGE_FORMAT => "png", + DOT_PATH => "/usr/bin/dot", + DOT_TRANSPARENT => "YES", +); + +# These are the keys that are safe to take from the output and include +# in the output; they may still need to be checked for safe values (if +# file paths). +my @safe = qw( +INPUT +FILE_PATTERNS +EXAMPLE_PATH +EXAMPLE_PATTERNS +IMAGE_PATH +INCLUDE_PATH +INCLUDE_FILE_PATTERNS +DOXYFILE_ENCODING +PROJECT_NAME +PROJECT_NUMBER +CREATE_SUBDIRS +OUTPUT_LANGUAGE +BRIEF_MEMBER_DESC +REPEAT_BRIEF +ABBREVIATE_BRIEF +ALWAYS_DETAILED_SEC +INLINE_INHERITED_MEMB +STRIP_FROM_PATH +STRIP_FROM_INC_PATH +JAVADOC_AUTOBRIEF +QT_AUTOBRIEF +MULTILINE_CPP_IS_BRIEF +INHERIT_DOCS +SEPARATE_MEMBER_PAGES +TAB_SIZE +ALIASES +OPTIMIZE_OUTPUT_FOR_C +OPTIMIZE_OUTPUT_JAVA +OPTIMIZE_FOR_FORTRAN +OPTIMIZE_OUTPUT_VHDL +EXTENSION_MAPPING +BUILTIN_STL_SUPPORT +CPP_CLI_SUPPORT +SIP_SUPPORT +IDL_PROPERTY_SUPPORT +DISTRIBUTE_GROUP_DOC +SUBGROUPING +TYPEDEF_HIDES_STRUCT +EXTRACT_ALL +EXTRACT_PRIVATE +EXTRACT_STATIC +EXTRACT_LOCAL_CLASSES +EXTRACT_LOCAL_METHODS +EXTRACT_ANON_NSPACES +HIDE_UNDOC_MEMBERS +HIDE_UNDOC_CLASSES +HIDE_FRIEND_COMPOUNDS +HIDE_IN_BODY_DOCS +INTERNAL_DOCS +HIDE_SCOPE_NAMES +SHOW_INCLUDE_FILES +FORCE_LOCAL_INCLUDES +INLINE_INFO +SORT_MEMBER_DOCS +SORT_BRIEF_DOCS +SORT_MEMBERS_CTORS_1ST +SORT_GROUP_NAMES +SORT_BY_SCOPE_NAME +GENERATE_TODOLIST +GENERATE_TESTLIST +GENERATE_BUGLIST +GENERATE_DEPRECATEDLIST +ENABLED_SECTIONS +MAX_INITIALIZER_LINES +SHOW_USED_FILES +SHOW_DIRECTORIES +SHOW_FILES +SHOW_NAMESPACES +QUIET +WARNINGS +WARN_IF_UNDOCUMENTED +WARN_IF_DOC_ERROR +WARN_NO_PARAMDOC +INPUT_ENCODING +RECURSIVE +EXCLUDE +EXCLUDE_SYMLINKS +EXCLUDE_PATTERNS +EXCLUDE_SYMBOLS +EXAMPLE_RECURSIVE +SOURCE_BROWSER +INLINE_SOURCES +STRIP_CODE_COMMENTS +REFERENCED_BY_RELATION +REFERENCES_RELATION +REFERENCES_LINK_SOURCE +VERBATIM_HEADERS +ALPHABETICAL_INDEX +COLS_IN_ALPHA_INDEX +IGNORE_PREFIX +HTML_TIMESTAMP +HTML_ALIGN_MEMBERS +ENABLE_PREPROCESSING +MACRO_EXPANSION +EXPAND_ONLY_PREDEF +SEARCH_INCLUDES +PREDEFINED +EXPAND_AS_DEFINED +SKIP_FUNCTION_MACROS +ALLEXTERNALS +EXTERNAL_GROUPS +CLASS_DIAGRAMS +HIDE_UNDOC_RELATIONS +CLASS_GRAPH +COLLABORATION_GRAPH +GROUP_GRAPHS +UML_LOOK +TEMPLATE_RELATIONS +INCLUDE_GRAPH +INCLUDED_BY_GRAPH +CALL_GRAPH +CALLER_GRAPH +GRAPHICAL_HIERARCHY +DIRECTORY_GRAPH +DOT_GRAPH_MAX_NODES +MAX_DOT_GRAPH_DEPTH +DOT_MULTI_TARGETS +DOT_CLEANUP +); + +my %safehash; +for my $sk (@safe) { $safehash{$sk} = 1; } + +my @lines = split "\n", $txt; + +my %settings; + +sub is_safe { + my $key = shift; + defined $safehash{$key} and $safehash{$key} == 1; +} + +sub has_file_path { + # Returns true if the given key expects a file path as a value. + # We only need to test keys that are safe; unsafe keys have been + # rejected already. + my $key = shift; + $key eq "INPUT" or + $key =~ /^OUTPUT_/ or + $key =~ /_PATH$/ or + $key =~ /_PATTERNS$/; +} + +sub is_safe_file_path { + my $value = shift; + not $value =~ /^\// and not $value =~ /\.\./; +} + +foreach my $line (@lines) { + + chomp $line; + my ($key, $value) = split /\s*=\s*/, $line; + + next if !defined $key; + + if ($key =~ /^GENERATE_/ and not $key =~ /LIST$/) { + print STDERR "NOTE: Setting $key explicitly to NO\n"; + $settings{$key} = "NO"; + next; + } + + if (!is_safe($key)) { + print STDERR "NOTE: Skipping non-whitelisted key $key\n"; + next; + } + + if (has_file_path($key) and !is_safe_file_path($value)) { + print STDERR "ERROR: Unsafe file path \"$value\" for key $key\n"; + exit 1; + } + + $settings{$key} = $value; +} + +foreach my $key (keys %fixed) { + my $value = $fixed{$key}; + print STDERR "NOTE: Setting $key to fixed value $value\n"; + $settings{$key} = $value; +} + +print join "\n", map { "$_ = $settings{$_}" } keys %settings; +print "\n";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/soundsoftware/extract-docs.sh Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,149 @@ +#!/bin/bash + +# Run this script from anywhere + +# Enumerate Hg repos; make sure they're up to date; extract docs for +# each + +hgdir="/var/hg" +docdir="/var/doc" +logfile="/var/www/test-cannam/log/extract-docs.log" + +redgrp="redmine" + +apikey="" +apihost="" +apiuser="" +apipass="" + +progdir=$(dirname $0) +case "$progdir" in + /*) ;; + *) progdir="$(pwd)/$progdir" ;; +esac + +types="doxygen javadoc" # Do Doxygen first (it can be used for Java too) + +for x in $types; do + if [ ! -x "$progdir/extract-$x.sh" ]; then + echo "Helper script not available: $progdir/extract-$x.sh" + exit 1 + fi +done + +enable_embedded() +{ + p="$1" + if [ -n "$apikey" ]; then + if [ -n "$apiuser" ]; then + sudo -u docgen curl -u "$apiuser":"$apipass" "http://$apihost/sys/projects/$p/embedded.xml?enable=1&key=$apikey" -d "" + else + sudo -u docgen curl "http://$apihost/sys/projects/$p/embedded.xml?enable=1&key=$apikey" -d "" + fi + else + echo "Can't enable Embedded, API not configured" 1>&2 + fi +} + +# We want to ensure the doc extraction is done by the unprivileged +# user docgen, which is not a member of any interesting group +# +# To this end, we create the tmpdir with user docgen and group +# www-data, and use the www-data user to pull out an archive of the Hg +# repo tip into a location beneath that, before using the docgen user +# to extract docs from that location and write them into the tmpdir + +# Same tmpdir for each project: we delete and recreate to avoid +# cleanup duty from lots of directories being created +# +tmpdir=$(mktemp -d "$docdir/tmp_XXXXXX") + +fail() +{ + message="$1" + echo "$message" 1>&2 + case "$tmpdir" in + */tmp*) rm -rf "$tmpdir";; + *);; + esac + exit 1 +} + +case "$tmpdir" in + /*) ;; + *) fail "Temporary directory creation failed";; +esac + +chown docgen.www-data "$tmpdir" || fail "Temporary directory ownership change failed" +chmod g+rwx "$tmpdir" || fail "Temporary directory permissions change failed" + +for projectdir in "$hgdir"/* ; do + + if [ -d "$projectdir" ] && [ -d "$projectdir/.hg" ]; then + + if ! sudo -u www-data hg -R "$projectdir" -q update; then + echo "Failed to update Hg in $projectdir, skipping" 1>&2 + continue + fi + + project=$(basename "$projectdir") + + tmptargetdir="$tmpdir/doc" + snapshotdir="$tmpdir/hgsnapshot" + + rm -rf "$tmptargetdir" "$snapshotdir" + + mkdir -m 770 "$tmptargetdir" || fail "Temporary target directory creation failed" + chown docgen.www-data "$tmptargetdir" || fail "Temporary target directory ownership change failed" + + mkdir -m 770 "$snapshotdir" || fail "Snapshot directory creation failed" + chown docgen.www-data "$snapshotdir" || fail "Snapshot directory ownership change failed" + + hgparents=$(sudo -u www-data hg -R "$projectdir" parents) + if [ -z "$hgparents" ]; then + echo "Hg repo at $projectdir has no working copy (empty repo?), skipping" + continue + else + echo "Found non-empty Hg repo: $projectdir for project $project" + fi + + if ! sudo -u www-data hg -R "$projectdir" archive -r tip -t files "$snapshotdir"; then + echo "Failed to pick archive from $projectdir, skipping" 1>&2 + continue + fi + + targetdir="$docdir/$project" + + echo "Temporary dir is $tmpdir, temporary doc dir is $tmptargetdir, snapshot dir is $snapshotdir, eventual target is $targetdir" + + for x in $types; do + if sudo -u docgen "$progdir/extract-$x.sh" "$project" "$snapshotdir" "$tmptargetdir" >> "$logfile" 2>&1; then + break + else + echo "Failed to extract via type $x" + fi + done + + if [ -f "$tmptargetdir/index.html" ]; then + echo "Processing resulted in an index.html being created, looks good!" + if [ ! -d "$targetdir" ] || [ ! -f "$targetdir/index.html" ]; then + echo "This project hasn't had doc extracted before: enabling Embedded" + enable_embedded "$project" + fi + + if [ -d "$targetdir" ]; then + mv "$targetdir" "$targetdir"_"$$" && \ + mv "$tmptargetdir" "$targetdir" && \ + rm -rf "$targetdir"_"$$" + chgrp -R "$redgrp" "$targetdir" + else + mv "$tmptargetdir" "$targetdir" + chgrp -R "$redgrp" "$targetdir" + fi + else + echo "Processing did not result in an index.html being created" + fi + fi +done + +rm -rf "$tmpdir"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/soundsoftware/extract-doxygen.sh Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,49 @@ +#!/bin/bash + +docdir="/var/doc" + +progdir=$(dirname $0) +case "$progdir" in + /*) ;; + *) progdir="$(pwd)/$progdir" ;; +esac + +project="$1" +projectdir="$2" +targetdir="$3" + +if [ -z "$project" ] || [ -z "$targetdir" ] || [ -z "$projectdir" ]; then + echo "Usage: $0 <project> <projectdir> <targetdir>" + exit 2 +fi + +if [ ! -d "$projectdir" ]; then + echo "Project directory $projectdir not found" + exit 1 +fi + +if [ ! -d "$targetdir" ]; then + echo "Target dir $targetdir not found" + exit 1 +fi + +if [ -f "$targetdir/index.html" ]; then + echo "Target dir $targetdir already contains index.html" + exit 1 +fi + +doxyfile=$(find "$projectdir" -type f -name Doxyfile -print | head -1) + +if [ -z "$doxyfile" ]; then + echo "No Doxyfile found for project $project" + exit 1 +fi + +echo "Project $project contains a Doxyfile at $doxyfile" + +cd "$projectdir" || exit 1 + +"$progdir/doxysafe.pl" "$doxyfile" | \ + sed -e '$a OUTPUT_DIRECTORY='"$targetdir" | \ + doxygen - +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/soundsoftware/extract-javadoc.sh Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,72 @@ +#!/bin/bash + +docdir="/var/doc" + +project="$1" +projectdir="$2" +targetdir="$3" + +if [ -z "$project" ] || [ -z "$targetdir" ] || [ -z "$projectdir" ]; then + echo "Usage: $0 <project> <projectdir> <targetdir>" + exit 2 +fi + +if [ ! -d "$projectdir" ]; then + echo "Project directory $projectdir not found" + exit 1 +fi + +if [ ! -d "$targetdir" ]; then + echo "Target dir $targetdir not found" + exit 1 +fi + +if [ -f "$targetdir/index.html" ]; then + echo "Target dir $targetdir already contains index.html" + exit 1 +fi + +# Identify Java files whose packages match the trailing parts of their +# paths, and list the resulting packages and the path prefixes with +# the packages removed (so as to find code in subdirs, +# e.g. src/com/example/...) + +# Regexp match is very rough; check what is actually permitted for +# package declarations + +find "$projectdir" -type f -name \*.java \ + -exec grep '^ *package [a-zA-Z][a-zA-Z0-9\._-]*; *$' \{\} /dev/null \; | + sed -e 's/\/[^\/]*: *package */:/' -e 's/; *$//' | + sort | uniq | ( + current_prefix= + current_packages= + while IFS=: read filepath package; do + echo "Looking at $package in $filepath" + packagepath=${package//./\/} + prefix=${filepath%$packagepath} + prefix=${prefix:=$projectdir} + if [ "$prefix" = "$filepath" ]; then + echo "Package $package does not match suffix of path $filepath, skipping" + continue + fi + if [ "$prefix" != "$current_prefix" ]; then + if [ -n "$current_packages" ]; then + echo "Running Javadoc for packages $current_packages from prefix $current_prefix" + javadoc -sourcepath "$current_prefix" -d "$targetdir" -subpackages $current_packages + fi + current_prefix="$prefix" + current_packages= + else + current_packages="$current_packages $package" + fi + done + prefix=${prefix:=$projectdir} + if [ -n "$current_packages" ]; then + echo "Running Javadoc for packages $current_packages in prefix $current_prefix" + javadoc -sourcepath "$current_prefix" -d "$targetdir" -subpackages $current_packages + fi + ) + +# for exit code: +[ -f "$targetdir/index.html" ] +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/soundsoftware/reposman-soundsoftware.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,347 @@ +#!/usr/bin/env ruby + +# == Synopsis +# +# reposman: manages your repositories with Redmine +# +# == Usage +# +# reposman [OPTIONS...] -s [DIR] -r [HOST] +# +# Examples: +# reposman --svn-dir=/var/svn --redmine-host=redmine.example.net --scm subversion +# reposman -s /var/git -r redmine.example.net -u http://svn.example.net --scm git +# +# == Arguments (mandatory) +# +# -s, --svn-dir=DIR use DIR as base directory for svn repositories +# -r, --redmine-host=HOST assume Redmine is hosted on HOST. Examples: +# -r redmine.example.net +# -r http://redmine.example.net +# -r https://example.net/redmine +# -k, --key=KEY use KEY as the Redmine API key +# +# == Options +# +# -o, --owner=OWNER owner of the repository. using the rails login +# allow user to browse the repository within +# Redmine even for private project. If you want to +# share repositories through Redmine.pm, you need +# to use the apache owner. +# -g, --group=GROUP group of the repository. (default: root) +# --scm=SCM the kind of SCM repository you want to create (and +# register) in Redmine (default: Subversion). +# reposman is able to create Git and Subversion +# repositories. For all other kind, you must specify +# a --command option +# -u, --url=URL the base url Redmine will use to access your +# repositories. This option is used to automatically +# register the repositories in Redmine. The project +# identifier will be appended to this url. Examples: +# -u https://example.net/svn +# -u file:///var/svn/ +# if this option isn't set, reposman will register +# the repositories with local file paths in Redmine +# -c, --command=COMMAND use this command instead of "svnadmin create" to +# create a repository. This option can be used to +# create repositories other than subversion and git +# kind. +# This command override the default creation for git +# and subversion. +# --http-user=USER User for HTTP Basic authentication with Redmine WS +# --http-pass=PASSWORD Password for Basic authentication with Redmine WS +# -t, --test only show what should be done +# -h, --help show help and exit +# -v, --verbose verbose +# -V, --version print version and exit +# -q, --quiet no log +# +# == References +# +# You can find more information on the redmine's wiki : http://www.redmine.org/wiki/redmine/HowTos + + +require 'getoptlong' +require 'rdoc/usage' +require 'find' +require 'etc' + +Version = "1.3" +SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem ) + +opts = GetoptLong.new( + ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT], + ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT], + ['--key', '-k', GetoptLong::REQUIRED_ARGUMENT], + ['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT], + ['--group', '-g', GetoptLong::REQUIRED_ARGUMENT], + ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT], + ['--command' , '-c', GetoptLong::REQUIRED_ARGUMENT], + ['--scm', GetoptLong::REQUIRED_ARGUMENT], + ['--http-user', GetoptLong::REQUIRED_ARGUMENT], + ['--http-pass', GetoptLong::REQUIRED_ARGUMENT], + ['--test', '-t', GetoptLong::NO_ARGUMENT], + ['--verbose', '-v', GetoptLong::NO_ARGUMENT], + ['--version', '-V', GetoptLong::NO_ARGUMENT], + ['--help' , '-h', GetoptLong::NO_ARGUMENT], + ['--quiet' , '-q', GetoptLong::NO_ARGUMENT] + ) + +$verbose = 0 +$quiet = false +$redmine_host = '' +$repos_base = '' +$http_user = '' +$http_pass = '' +$svn_owner = 'root' +$svn_group = 'root' +$use_groupid = true +$svn_url = false +$test = false +$scm = 'Subversion' + +def log(text, options={}) + level = options[:level] || 0 + puts text unless $quiet or level > $verbose + exit 1 if options[:exit] +end + +def system_or_raise(command) + raise "\"#{command}\" failed" unless system command +end + +module SCM + + module Subversion + def self.create(path) + system_or_raise "svnadmin create #{path}" + end + end + + module Git + def self.create(path) + Dir.mkdir path + Dir.chdir(path) do + system_or_raise "git --bare init --shared" + system_or_raise "git update-server-info" + end + end + end + +end + +begin + opts.each do |opt, arg| + case opt + when '--svn-dir'; $repos_base = arg.dup + when '--redmine-host'; $redmine_host = arg.dup + when '--key'; $api_key = arg.dup + when '--owner'; $svn_owner = arg.dup; $use_groupid = false; + when '--group'; $svn_group = arg.dup; $use_groupid = false; + when '--url'; $svn_url = arg.dup + when '--scm'; $scm = arg.dup.capitalize; log("Invalid SCM: #{$scm}", :exit => true) unless SUPPORTED_SCM.include?($scm) + when '--http-user'; $http_user = arg.dup + when '--http-pass'; $http_pass = arg.dup + when '--command'; $command = arg.dup + when '--verbose'; $verbose += 1 + when '--test'; $test = true + when '--version'; puts Version; exit + when '--help'; RDoc::usage + when '--quiet'; $quiet = true + end + end +rescue + exit 1 +end + +if $test + log("running in test mode") +end + +# Make sure command is overridden if SCM vendor is not handled internally (for the moment Subversion and Git) +if $command.nil? + begin + scm_module = SCM.const_get($scm) + rescue + log("Please use --command option to specify how to create a #{$scm} repository.", :exit => true) + end +end + +$svn_url += "/" if $svn_url and not $svn_url.match(/\/$/) + +if ($redmine_host.empty? or $repos_base.empty?) + RDoc::usage +end + +unless File.directory?($repos_base) + log("directory '#{$repos_base}' doesn't exists", :exit => true) +end + +begin + require 'active_resource' +rescue LoadError + log("This script requires activeresource.\nRun 'gem install activeresource' to install it.", :exit => true) +end + +class Project < ActiveResource::Base + self.headers["User-agent"] = "Redmine repository manager/#{Version}" +end + +log("querying Redmine for projects...", :level => 1); + +$redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://") +$redmine_host.gsub!(/\/$/, '') + +Project.site = "#{$redmine_host}/sys"; +Project.user = $http_user; +Project.password = $http_pass; + +begin + # Get all active projects that have the Repository module enabled + projects = Project.find(:all, :params => {:key => $api_key}) +rescue => e + log("Unable to connect to #{Project.site}: #{e}", :exit => true) +end + +if projects.nil? + log('no project found, perhaps you forgot to "Enable WS for repository management"', :exit => true) +end + +log("retrieved #{projects.size} projects", :level => 1) + +def set_owner_and_rights(project, repos_path, &block) + if mswin? + yield if block_given? + else + uid, gid = Etc.getpwnam($svn_owner).uid, ($use_groupid ? Etc.getgrnam(project.identifier).gid : Etc.getgrnam($svn_group).gid) + right = project.is_public ? 02775 : 02770 + yield if block_given? + Find.find(repos_path) do |f| + File.chmod right, f + File.chown uid, gid, f + end + end +end + +def other_read_right?(file) + (File.stat(file).mode & 0007).zero? ? false : true +end + +def owner_name(file) + mswin? ? + $svn_owner : + Etc.getpwuid( File.stat(file).uid ).name +end + +def mswin? + (RUBY_PLATFORM =~ /(:?mswin|mingw)/) || (RUBY_PLATFORM == 'java' && (ENV['OS'] || ENV['os']) =~ /windows/i) +end + +projects.each do |project| + log("treating project #{project.name}", :level => 1) + + if project.identifier.empty? + log("\tno identifier for project #{project.name}") + next + elsif not project.identifier.match(/^[a-z0-9\-]+$/) + log("\tinvalid identifier for project #{project.name} : #{project.identifier}"); + next; + end + + repos_path = File.join($repos_base, project.identifier).gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR) + + create_repos = false + # Logic required for SoundSoftware.ac.uk repositories: + # + # * If the project has a repository path declared already, + # - if it's a local path, + # - if it does not exist + # - if it has the right root + # - create it + # - else + # - leave alone (remote repository) + # * else + # - create repository with same name as project + # - set to project + + if project.respond_to?(:repository) + + repos_url = project.repository.url; + log("\texisting url for project #{project.identifier} is #{repos_url}"); + + if repos_url.match(/^file:\//) || repos_url.match(/^\//) + + repos_url = repos_url.gsub(/^file:\/*/, "/"); + log("\tthis is a local file path, at #{repos_url}"); + + if repos_url.slice(0, $repos_base.length) != $repos_base + log("\tit is in the wrong place: replacing it"); + # leave repos_path set to our original suggestion + create_repos = true + else + if !File.directory?(repos_url) + log("\tit doesn't exist; we should create it"); + repos_path = repos_url + create_repos = true + else + log("\tit exists and is in the right place"); + end + end + else + log("\tthis is a remote path, leaving alone"); + end + else + log("\tproject #{project.identifier} has no repository registered") +# if File.directory?(repos_path) +# log("\trepository path #{repos_path} already exists, not creating") +# else + create_repos = true +# end + end + + if create_repos + + registration_url = repos_path + if $svn_url + registration_url = "#{$svn_url}#{project.identifier}" + end + + if $test + log("\tproposal: create repository #{repos_path}") + log("\tproposal: register repository #{repos_path} in Redmine with vendor #{$scm}, url #{registration_url}") + next + end + +# No -- we need "other" users to be able to read it. Access control +# is not handled through Unix user id anyway +# project.is_public ? File.umask(0002) : File.umask(0007) + File.umask(0002) + + log("\taction: create repository #{repos_path}") + + begin + if !File.directory?(repos_path) + set_owner_and_rights(project, repos_path) do + if scm_module.nil? + log("\trunning command: #{$command} #{repos_path}") + system_or_raise "#{$command} #{repos_path}" + else + scm_module.create(repos_path) + end + end + end + rescue => e + log("\tunable to create #{repos_path} : #{e}\n") + next + end + + begin + log("\taction: register repository #{repos_path} in Redmine with vendor #{$scm}, url #{registration_url}"); + project.post(:repository, :vendor => $scm, :repository => {:url => "#{registration_url}"}, :key => $api_key) + rescue => e + log("\trepository #{repos_path} not registered in Redmine: #{e.message}"); + end + log("\trepository #{repos_path} created"); + end +end +
--- a/extra/svn/reposman.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/extra/svn/reposman.rb Mon Jun 06 14:41:04 2011 +0100 @@ -48,6 +48,8 @@ # kind. # This command override the default creation for git # and subversion. +# --http-user=USER User for HTTP Basic authentication with Redmine WS +# --http-pass=PASSWORD Password for Basic authentication with Redmine WS # -f, --force force repository creation even if the project # repository is already declared in Redmine # -t, --test only show what should be done @@ -78,6 +80,8 @@ ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT], ['--command' , '-c', GetoptLong::REQUIRED_ARGUMENT], ['--scm', GetoptLong::REQUIRED_ARGUMENT], + ['--http-user', GetoptLong::REQUIRED_ARGUMENT], + ['--http-pass', GetoptLong::REQUIRED_ARGUMENT], ['--test', '-t', GetoptLong::NO_ARGUMENT], ['--force', '-f', GetoptLong::NO_ARGUMENT], ['--verbose', '-v', GetoptLong::NO_ARGUMENT], @@ -90,6 +94,8 @@ $quiet = false $redmine_host = '' $repos_base = '' +$http_user = '' +$http_pass = '' $svn_owner = 'root' $svn_group = 'root' $use_groupid = true @@ -138,6 +144,8 @@ when '--group'; $svn_group = arg.dup; $use_groupid = false; when '--url'; $svn_url = arg.dup when '--scm'; $scm = arg.dup.capitalize; log("Invalid SCM: #{$scm}", :exit => true) unless SUPPORTED_SCM.include?($scm) + when '--http-user'; $http_user = arg.dup + when '--http-pass'; $http_pass = arg.dup when '--command'; $command = arg.dup when '--verbose'; $verbose += 1 when '--test'; $test = true @@ -190,6 +198,8 @@ $redmine_host.gsub!(/\/$/, '') Project.site = "#{$redmine_host}/sys"; +Project.user = $http_user; +Project.password = $http_pass; begin # Get all active projects that have the Repository module enabled @@ -306,3 +316,4 @@ log("\trepository #{repos_path} created"); end end +
--- a/lib/redmine/info.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/lib/redmine/info.rb Mon Jun 06 14:41:04 2011 +0100 @@ -3,7 +3,7 @@ class << self def app_name; 'Redmine' end def url; 'http://www.redmine.org/' end - def help_url; 'http://www.redmine.org/guide' end + def help_url; '/projects/soundsoftware-site/wiki/Help' end def versioned_name; "#{app_name} #{Redmine::VERSION}" end # Creates the url string to a specific Redmine issue
--- a/lib/redmine/scm/adapters/mercurial/hg-template-0.9.5.tmpl Mon Jun 06 14:24:13 2011 +0100 +++ b/lib/redmine/scm/adapters/mercurial/hg-template-0.9.5.tmpl Mon Jun 06 14:41:04 2011 +0100 @@ -9,4 +9,4 @@ file_copy = '<path-copied copyfrom-path="{source|urlescape}">{name|urlescape}</path-copied>\n' tag = '<tag>{tag|escape}</tag>\n' header='<?xml version="1.0" encoding="UTF-8" ?>\n<log>\n\n' -# footer="</log>" \ No newline at end of file +footer='</log>'
--- a/lib/redmine/scm/adapters/mercurial/hg-template-1.0.tmpl Mon Jun 06 14:24:13 2011 +0100 +++ b/lib/redmine/scm/adapters/mercurial/hg-template-1.0.tmpl Mon Jun 06 14:41:04 2011 +0100 @@ -9,4 +9,4 @@ file_copy = '<path-copied copyfrom-path="{source|urlescape}">{name|urlescape}</path-copied>\n' tag = '<tag>{tag|escape}</tag>\n' header='<?xml version="1.0" encoding="UTF-8" ?>\n<log>\n\n' -# footer="</log>" +footer='</log>'
--- a/lib/redmine/scm/adapters/mercurial_adapter.rb Mon Jun 06 14:24:13 2011 +0100 +++ b/lib/redmine/scm/adapters/mercurial_adapter.rb Mon Jun 06 14:41:04 2011 +0100 @@ -192,8 +192,7 @@ output.force_encoding('UTF-8') end begin - # Mercurial < 1.5 does not support footer template for '</log>' - ActiveSupport::XmlMini.parse("#{output}</log>")['log'] + ActiveSupport::XmlMini.parse("#{output}")['log'] rescue end end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/redmine/views/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,23 @@ +K 25 +svn:wc:ra_dav:version-url +V 42 +/svn/!svn/ver/4489/trunk/lib/redmine/views +END +api_template_handler.rb +K 25 +svn:wc:ra_dav:version-url +V 66 +/svn/!svn/ver/4452/trunk/lib/redmine/views/api_template_handler.rb +END +other_formats_builder.rb +K 25 +svn:wc:ra_dav:version-url +V 67 +/svn/!svn/ver/2334/trunk/lib/redmine/views/other_formats_builder.rb +END +builders.rb +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/4452/trunk/lib/redmine/views/builders.rb +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/redmine/views/builders/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,23 @@ +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/4489/trunk/lib/redmine/views/builders +END +structure.rb +K 25 +svn:wc:ra_dav:version-url +V 64 +/svn/!svn/ver/4489/trunk/lib/redmine/views/builders/structure.rb +END +xml.rb +K 25 +svn:wc:ra_dav:version-url +V 58 +/svn/!svn/ver/4489/trunk/lib/redmine/views/builders/xml.rb +END +json.rb +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/4452/trunk/lib/redmine/views/builders/json.rb +END
--- a/public/javascripts/application.js Mon Jun 06 14:24:13 2011 +0100 +++ b/public/javascripts/application.js Mon Jun 06 14:41:04 2011 +0100 @@ -369,3 +369,7 @@ } Event.observe(window, 'load', hideOnLoad); + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/public/javascripts/ssamr_institutions.js Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,32 @@ + + +/* SSAMR specific functions */ + +/* institution related functions */ +Event.observe(window, 'load', + function() { + $('ssamr_user_details_institution_type_true').observe('click', function(e, el) { + $('ssamr_user_details_other_institution').disable(); + $('ssamr_user_details_institution_id').enable(); + }); + + $('ssamr_user_details_institution_type_false').observe('click', function(e, el) { + $('ssamr_user_details_other_institution').enable(); + $('ssamr_user_details_institution_id').disable(); + }); + + if($('ssamr_user_details_institution_type_true').checked) + $('ssamr_user_details_other_institution').disable(); + else if($('ssamr_user_details_institution_type_false').checked) + $('ssamr_user_details_institution_id').disable(); + else { + $('ssamr_user_details_other_institution').disable(); + $('ssamr_user_details_institution_id').enable(); + $('ssamr_user_details_institution_type_true').checked = true; + $('ssamr_user_details_institution_type_false').checked = false; + } +} +); + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/public/javascripts/ssamr_registration.js Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,19 @@ + + +/* SSAMR specific functions */ + +/* institution related functions */ +Event.observe(window, 'load', + function() { + + if(!$('ssamr_user_details_institution_type_true').checked && $('ssamr_user_details_institution_type_true').checked){ + $('ssamr_user_details_other_institution').disable(); + $('ssamr_user_details_institution_id').enable(); + $('ssamr_user_details_institution_type_true').checked = true; + $('ssamr_user_details_institution_type_false').checked = false; + } + } +); + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/public/stylesheets/.svn/tmp/application.css.tmp Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,951 @@ +html {overflow-y:scroll;} +body { font-family: Verdana, sans-serif; font-size: 12px; color:#484848; margin: 0; padding: 0; min-width: 900px; } + +h1, h2, h3, h4 { font-family: "Trebuchet MS", Verdana, sans-serif;} +h1 {margin:0; padding:0; font-size: 24px;} +h2, .wiki h1 {font-size: 20px;padding: 2px 10px 1px 0px;margin: 0 0 10px 0; border-bottom: 1px solid #bbbbbb; color: #444;} +h3, .wiki h2 {font-size: 16px;padding: 2px 10px 1px 0px;margin: 0 0 10px 0; border-bottom: 1px solid #bbbbbb; color: #444;} +h4, .wiki h3 {font-size: 13px;padding: 2px 10px 1px 0px;margin-bottom: 5px; border-bottom: 1px dotted #bbbbbb; color: #444;} + +/***** Layout *****/ +#wrapper {background: white;} + +#top-menu {background: #2C4056; color: #fff; height:1.8em; font-size: 0.8em; padding: 2px 2px 0px 6px;} +#top-menu ul {margin: 0; padding: 0;} +#top-menu li { + float:left; + list-style-type:none; + margin: 0px 0px 0px 0px; + padding: 0px 0px 0px 0px; + white-space:nowrap; +} +#top-menu a {color: #fff; margin-right: 8px; font-weight: bold;} +#top-menu #loggedas { float: right; margin-right: 0.5em; color: #fff; } + +#account {float:right;} + +#header {height:5.3em;margin:0;background-color:#507AAA;color:#f8f8f8; padding: 4px 8px 0px 6px; position:relative;} +#header a {color:#f8f8f8;} +#header h1 a.ancestor { font-size: 80%; } +#quick-search {float:right;} + +#main-menu {position: absolute; bottom: 0px; left:6px; margin-right: -500px;} +#main-menu ul {margin: 0; padding: 0;} +#main-menu li { + float:left; + list-style-type:none; + margin: 0px 2px 0px 0px; + padding: 0px 0px 0px 0px; + white-space:nowrap; +} +#main-menu li a { + display: block; + color: #fff; + text-decoration: none; + font-weight: bold; + margin: 0; + padding: 4px 10px 4px 10px; +} +#main-menu li a:hover {background:#759FCF; color:#fff;} +#main-menu li a.selected, #main-menu li a.selected:hover {background:#fff; color:#555;} + +#admin-menu ul {margin: 0; padding: 0;} +#admin-menu li {margin: 0; padding: 0 0 12px 0; list-style-type:none;} + +#admin-menu a { background-position: 0% 40%; background-repeat: no-repeat; padding-left: 20px; padding-top: 2px; padding-bottom: 3px;} +#admin-menu a.projects { background-image: url(../images/projects.png); } +#admin-menu a.users { background-image: url(../images/user.png); } +#admin-menu a.groups { background-image: url(../images/group.png); } +#admin-menu a.roles { background-image: url(../images/database_key.png); } +#admin-menu a.trackers { background-image: url(../images/ticket.png); } +#admin-menu a.issue_statuses { background-image: url(../images/ticket_edit.png); } +#admin-menu a.workflows { background-image: url(../images/ticket_go.png); } +#admin-menu a.custom_fields { background-image: url(../images/textfield.png); } +#admin-menu a.enumerations { background-image: url(../images/text_list_bullets.png); } +#admin-menu a.settings { background-image: url(../images/changeset.png); } +#admin-menu a.plugins { background-image: url(../images/plugin.png); } +#admin-menu a.info { background-image: url(../images/help.png); } +#admin-menu a.server_authentication { background-image: url(../images/server_key.png); } + +#main {background-color:#EEEEEE;} + +#sidebar{ float: right; width: 22%; position: relative; z-index: 9; padding: 0; margin: 0;} +* html #sidebar{ width: 22%; } +#sidebar h3{ font-size: 14px; margin-top:14px; color: #666; } +#sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; } +* html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; } +#sidebar .contextual { margin-right: 1em; } + +#content { width: 75%; background-color: #fff; margin: 0px; border-right: 1px solid #ddd; padding: 6px 10px 10px 10px; z-index: 10; } +* html #content{ width: 75%; padding-left: 0; margin-top: 0px; padding: 6px 10px 10px 10px;} +html>body #content { min-height: 600px; } +* html body #content { height: 600px; } /* IE */ + +#main.nosidebar #sidebar{ display: none; } +#main.nosidebar #content{ width: auto; border-right: 0; } + +#footer {clear: both; border-top: 1px solid #bbb; font-size: 0.9em; color: #aaa; padding: 5px; text-align:center; background:#fff;} + +#login-form table {margin-top:5em; padding:1em; margin-left: auto; margin-right: auto; border: 2px solid #FDBF3B; background-color:#FFEBC1; } +#login-form table td {padding: 6px;} +#login-form label {font-weight: bold;} +#login-form input#username, #login-form input#password { width: 300px; } + +input#openid_url { background: url(../images/openid-bg.gif) no-repeat; background-color: #fff; background-position: 0 50%; padding-left: 18px; } + +.clear:after{ content: "."; display: block; height: 0; clear: both; visibility: hidden; } + +/***** Links *****/ +a, a:link, a:visited{ color: #2A5685; text-decoration: none; } +a:hover, a:active{ color: #c61a1a; text-decoration: underline;} +a img{ border: 0; } + +a.issue.closed, a.issue.closed:link, a.issue.closed:visited { color: #999; text-decoration: line-through; } + +/***** Tables *****/ +table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; } +table.list th { background-color:#EEEEEE; padding: 4px; white-space:nowrap; } +table.list td { vertical-align: top; } +table.list td.id { width: 2%; text-align: center;} +table.list td.checkbox { width: 15px; padding: 0px;} +table.list td.buttons { width: 15%; white-space:nowrap; text-align: right; } +table.list td.buttons a { padding-right: 0.6em; } +table.list caption { text-align: left; padding: 0.5em 0.5em 0.5em 0; } + +tr.project td.name a { white-space:nowrap; } + +tr.project.idnt td.name span {background: url(../images/bullet_arrow_right.png) no-repeat 0 50%; padding-left: 16px;} +tr.project.idnt-1 td.name {padding-left: 0.5em;} +tr.project.idnt-2 td.name {padding-left: 2em;} +tr.project.idnt-3 td.name {padding-left: 3.5em;} +tr.project.idnt-4 td.name {padding-left: 5em;} +tr.project.idnt-5 td.name {padding-left: 6.5em;} +tr.project.idnt-6 td.name {padding-left: 8em;} +tr.project.idnt-7 td.name {padding-left: 9.5em;} +tr.project.idnt-8 td.name {padding-left: 11em;} +tr.project.idnt-9 td.name {padding-left: 12.5em;} + +tr.issue { text-align: center; white-space: nowrap; } +tr.issue td.subject, tr.issue td.category, td.assigned_to { white-space: normal; } +tr.issue td.subject { text-align: left; } +tr.issue td.done_ratio table.progress { margin-left:auto; margin-right: auto;} + +tr.issue.idnt td.subject a {background: url(../images/bullet_arrow_right.png) no-repeat 0 50%; padding-left: 16px;} +tr.issue.idnt-1 td.subject {padding-left: 0.5em;} +tr.issue.idnt-2 td.subject {padding-left: 2em;} +tr.issue.idnt-3 td.subject {padding-left: 3.5em;} +tr.issue.idnt-4 td.subject {padding-left: 5em;} +tr.issue.idnt-5 td.subject {padding-left: 6.5em;} +tr.issue.idnt-6 td.subject {padding-left: 8em;} +tr.issue.idnt-7 td.subject {padding-left: 9.5em;} +tr.issue.idnt-8 td.subject {padding-left: 11em;} +tr.issue.idnt-9 td.subject {padding-left: 12.5em;} + +tr.entry { border: 1px solid #f8f8f8; } +tr.entry td { white-space: nowrap; } +tr.entry td.filename { width: 30%; } +tr.entry td.size { text-align: right; font-size: 90%; } +tr.entry td.revision, tr.entry td.author { text-align: center; } +tr.entry td.age { text-align: right; } +tr.entry.file td.filename a { margin-left: 16px; } + +tr span.expander {background-image: url(../images/bullet_toggle_plus.png); padding-left: 8px; margin-left: 0; cursor: pointer;} +tr.open span.expander {background-image: url(../images/bullet_toggle_minus.png);} + +tr.changeset td.author { text-align: center; width: 15%; } +tr.changeset td.committed_on { text-align: center; width: 15%; } + +table.files tr.file td { text-align: center; } +table.files tr.file td.filename { text-align: left; padding-left: 24px; } +table.files tr.file td.digest { font-size: 80%; } + +table.members td.roles, table.memberships td.roles { width: 45%; } + +tr.message { height: 2.6em; } +tr.message td.subject { padding-left: 20px; } +tr.message td.created_on { white-space: nowrap; } +tr.message td.last_message { font-size: 80%; white-space: nowrap; } +tr.message.locked td.subject { background: url(../images/locked.png) no-repeat 0 1px; } +tr.message.sticky td.subject { background: url(../images/bullet_go.png) no-repeat 0 1px; font-weight: bold; } + +tr.version.closed, tr.version.closed a { color: #999; } +tr.version td.name { padding-left: 20px; } +tr.version.shared td.name { background: url(../images/link.png) no-repeat 0% 70%; } +tr.version td.date, tr.version td.status, tr.version td.sharing { text-align: center; } + +tr.user td { width:13%; } +tr.user td.email { width:18%; } +tr.user td { white-space: nowrap; } +tr.user.locked, tr.user.registered { color: #aaa; } +tr.user.locked a, tr.user.registered a { color: #aaa; } + +tr.wiki-page-version td.updated_on, tr.wiki-page-version td.author {text-align:center;} + +tr.time-entry { text-align: center; white-space: nowrap; } +tr.time-entry td.subject, tr.time-entry td.comments { text-align: left; white-space: normal; } +td.hours { text-align: right; font-weight: bold; padding-right: 0.5em; } +td.hours .hours-dec { font-size: 0.9em; } + +table.plugins td { vertical-align: middle; } +table.plugins td.configure { text-align: right; padding-right: 1em; } +table.plugins span.name { font-weight: bold; display: block; margin-bottom: 6px; } +table.plugins span.description { display: block; font-size: 0.9em; } +table.plugins span.url { display: block; font-size: 0.9em; } + +table.list tbody tr.group td { padding: 0.8em 0 0.5em 0.3em; font-weight: bold; border-bottom: 1px solid #ccc; } +table.list tbody tr.group span.count { color: #aaa; font-size: 80%; } + +table.list tbody tr:hover { background-color:#ffffdd; } +table.list tbody tr.group:hover { background-color:inherit; } +table td {padding:2px;} +table p {margin:0;} +.odd {background-color:#f6f7f8;} +.even {background-color: #fff;} + +a.sort { padding-right: 16px; background-position: 100% 50%; background-repeat: no-repeat; } +a.sort.asc { background-image: url(../images/sort_asc.png); } +a.sort.desc { background-image: url(../images/sort_desc.png); } + +table.attributes { width: 100% } +table.attributes th { vertical-align: top; text-align: left; } +table.attributes td { vertical-align: top; } + +table.boards a.board, h3.comments { background: url(../images/comment.png) no-repeat 0% 50%; padding-left: 20px; } + +td.center {text-align:center;} + +h3.version { background: url(../images/package.png) no-repeat 0% 50%; padding-left: 20px; } + +div.issues h3 { background: url(../images/ticket.png) no-repeat 0% 50%; padding-left: 20px; } +div.members h3 { background: url(../images/group.png) no-repeat 0% 50%; padding-left: 20px; } +div.news h3 { background: url(../images/news.png) no-repeat 0% 50%; padding-left: 20px; } +div.projects h3 { background: url(../images/projects.png) no-repeat 0% 50%; padding-left: 20px; } + +#watchers ul {margin: 0; padding: 0;} +#watchers li {list-style-type:none;margin: 0px 2px 0px 0px; padding: 0px 0px 0px 0px;} +#watchers select {width: 95%; display: block;} +#watchers a.delete {opacity: 0.4;} +#watchers a.delete:hover {opacity: 1;} +#watchers img.gravatar {vertical-align: middle;margin: 0 4px 2px 0;} + +.highlight { background-color: #FCFD8D;} +.highlight.token-1 { background-color: #faa;} +.highlight.token-2 { background-color: #afa;} +.highlight.token-3 { background-color: #aaf;} + +.box{ +padding:6px; +margin-bottom: 10px; +background-color:#f6f6f6; +color:#505050; +line-height:1.5em; +border: 1px solid #e4e4e4; +} + +div.square { + border: 1px solid #999; + float: left; + margin: .3em .4em 0 .4em; + overflow: hidden; + width: .6em; height: .6em; +} +.contextual {float:right; white-space: nowrap; line-height:1.4em;margin-top:5px; padding-left: 10px; font-size:0.9em;} +.contextual input, .contextual select {font-size:0.9em;} +.message .contextual { margin-top: 0; } + +.splitcontentleft{float:left; width:49%;} +.splitcontentright{float:right; width:49%;} +form {display: inline;} +input, select {vertical-align: middle; margin-top: 1px; margin-bottom: 1px;} +fieldset {border: 1px solid #e4e4e4; margin:0;} +legend {color: #484848;} +hr { width: 100%; height: 1px; background: #ccc; border: 0;} +blockquote { font-style: italic; border-left: 3px solid #e0e0e0; padding-left: 0.6em; margin-left: 2.4em;} +blockquote blockquote { margin-left: 0;} +acronym { border-bottom: 1px dotted; cursor: help; } +textarea.wiki-edit { width: 99%; } +li p {margin-top: 0;} +div.issue {background:#ffffdd; padding:6px; margin-bottom:6px;border: 1px solid #d7d7d7;} +p.breadcrumb { font-size: 0.9em; margin: 4px 0 4px 0;} +p.subtitle { font-size: 0.9em; margin: -6px 0 12px 0; font-style: italic; } +p.footnote { font-size: 0.9em; margin-top: 0px; margin-bottom: 0px; } + +div.issue div.subject div div { padding-left: 16px; } +div.issue div.subject p {margin: 0; margin-bottom: 0.1em; font-size: 90%; color: #999;} +div.issue div.subject>div>p { margin-top: 0.5em; } +div.issue div.subject h3 {margin: 0; margin-bottom: 0.1em;} + +#issue_tree table.issues { border: 0; } +#issue_tree td.checkbox {display:none;} + +fieldset.collapsible { border-width: 1px 0 0 0; font-size: 0.9em; } +fieldset.collapsible legend { padding-left: 16px; background: url(../images/arrow_expanded.png) no-repeat 0% 40%; cursor:pointer; } +fieldset.collapsible.collapsed legend { background-image: url(../images/arrow_collapsed.png); } + +fieldset#date-range p { margin: 2px 0 2px 0; } +fieldset#filters table { border-collapse: collapse; } +fieldset#filters table td { padding: 0; vertical-align: middle; } +fieldset#filters tr.filter { height: 2em; } +fieldset#filters td.add-filter { text-align: right; vertical-align: top; } +.buttons { font-size: 0.9em; margin-bottom: 1.4em; margin-top: 1em; } + +div#issue-changesets {float:right; width:45%; margin-left: 1em; margin-bottom: 1em; background: #fff; padding-left: 1em; font-size: 90%;} +div#issue-changesets div.changeset { padding: 4px;} +div#issue-changesets div.changeset { border-bottom: 1px solid #ddd; } +div#issue-changesets p { margin-top: 0; margin-bottom: 1em;} + +div#activity dl, #search-results { margin-left: 2em; } +div#activity dd, #search-results dd { margin-bottom: 1em; padding-left: 18px; font-size: 0.9em; } +div#activity dt, #search-results dt { margin-bottom: 0px; padding-left: 20px; line-height: 18px; background-position: 0 50%; background-repeat: no-repeat; } +div#activity dt.me .time { border-bottom: 1px solid #999; } +div#activity dt .time { color: #777; font-size: 80%; } +div#activity dd .description, #search-results dd .description { font-style: italic; } +div#activity span.project:after, #search-results span.project:after { content: " -"; } +div#activity dd span.description, #search-results dd span.description { display:block; color: #808080; } + +#search-results dd { margin-bottom: 1em; padding-left: 20px; margin-left:0px; } + +div#search-results-counts {float:right;} +div#search-results-counts ul { margin-top: 0.5em; } +div#search-results-counts li { list-style-type:none; float: left; margin-left: 1em; } + +dt.issue { background-image: url(../images/ticket.png); } +dt.issue-edit { background-image: url(../images/ticket_edit.png); } +dt.issue-closed { background-image: url(../images/ticket_checked.png); } +dt.issue-note { background-image: url(../images/ticket_note.png); } +dt.changeset { background-image: url(../images/changeset.png); } +dt.news { background-image: url(../images/news.png); } +dt.message { background-image: url(../images/message.png); } +dt.reply { background-image: url(../images/comments.png); } +dt.wiki-page { background-image: url(../images/wiki_edit.png); } +dt.attachment { background-image: url(../images/attachment.png); } +dt.document { background-image: url(../images/document.png); } +dt.project { background-image: url(../images/projects.png); } +dt.time-entry { background-image: url(../images/time.png); } + +#search-results dt.issue.closed { background-image: url(../images/ticket_checked.png); } + +div#roadmap .related-issues { margin-bottom: 1em; } +div#roadmap .related-issues td.checkbox { display: none; } +div#roadmap .wiki h1:first-child { display: none; } +div#roadmap .wiki h1 { font-size: 120%; } +div#roadmap .wiki h2 { font-size: 110%; } + +div#version-summary { float:right; width:380px; margin-left: 16px; margin-bottom: 16px; background-color: #fff; } +div#version-summary fieldset { margin-bottom: 1em; } +div#version-summary .total-hours { text-align: right; } + +table#time-report td.hours, table#time-report th.period, table#time-report th.total { text-align: right; padding-right: 0.5em; } +table#time-report tbody tr { font-style: italic; color: #777; } +table#time-report tbody tr.last-level { font-style: normal; color: #555; } +table#time-report tbody tr.total { font-style: normal; font-weight: bold; color: #555; background-color:#EEEEEE; } +table#time-report .hours-dec { font-size: 0.9em; } + +form .attributes { margin-bottom: 8px; } +form .attributes p { padding-top: 1px; padding-bottom: 2px; } +form .attributes select { min-width: 50%; } + +ul.projects { margin: 0; padding-left: 1em; } +ul.projects.root { margin: 0; padding: 0; } +ul.projects ul.projects { border-left: 3px solid #e0e0e0; } +ul.projects li.root { list-style-type:none; margin-bottom: 1em; } +ul.projects li.child { list-style-type:none; margin-top: 1em;} +ul.projects div.root a.project { /* font-family: "Trebuchet MS", Verdana, sans-serif; */ font-weight: bold; font-size: 16px; margin: 0 0 10px 0; } +.my-project { padding-left: 18px; background: url(../images/fav.png) no-repeat 0 50%; } + +#tracker_project_ids ul { margin: 0; padding-left: 1em; } +#tracker_project_ids li { list-style-type:none; } + +ul.properties {padding:0; font-size: 0.9em; color: #777;} +ul.properties li {list-style-type:none;} +ul.properties li span {font-style:italic;} + +.total-hours { font-size: 110%; font-weight: bold; } +.total-hours span.hours-int { font-size: 120%; } + +.autoscroll {overflow-x: auto; padding:1px; margin-bottom: 1.2em;} +#user_firstname, #user_lastname, #user_mail, #my_account_form select { width: 90%; } + +#workflow_copy_form select { width: 200px; } + +.pagination {font-size: 90%} +p.pagination {margin-top:8px;} + +/***** Tabular forms ******/ +.tabular p{ +margin: 0; +padding: 5px 0 8px 0; +padding-left: 180px; /*width of left column containing the label elements*/ +height: 1%; +clear:left; +} + +html>body .tabular p {overflow:hidden;} + +.tabular label{ +font-weight: bold; +float: left; +text-align: right; +margin-left: -180px; /*width of left column*/ +width: 175px; /*width of labels. Should be smaller than left column to create some right +margin*/ +} + +.tabular label.floating{ +font-weight: normal; +margin-left: 0px; +text-align: left; +width: 270px; +} + +.tabular label.block{ +font-weight: normal; +margin-left: 0px !important; +text-align: left; +float: none; +display: block; +width: auto; +} + +.tabular label.inline{ +float:none; +margin-left: 5px !important; +width: auto; +} + +input#time_entry_comments { width: 90%;} + +#preview fieldset {margin-top: 1em; background: url(../images/draft.png)} + +.tabular.settings p{ padding-left: 300px; } +.tabular.settings label{ margin-left: -300px; width: 295px; } +.tabular.settings textarea { width: 99%; } + +fieldset.settings label { display: block; } +.parent { padding-left: 20px; } + +.required {color: #bb0000;} +.summary {font-style: italic;} + +#attachments_fields input[type=text] {margin-left: 8px; } + +div.attachments { margin-top: 12px; } +div.attachments p { margin:4px 0 2px 0; } +div.attachments img { vertical-align: middle; } +div.attachments span.author { font-size: 0.9em; color: #888; } + +p.other-formats { text-align: right; font-size:0.9em; color: #666; } +.other-formats span + span:before { content: "| "; } + +a.atom { background: url(../images/feed.png) no-repeat 1px 50%; padding: 2px 0px 3px 16px; } + +/* Project members tab */ +div#tab-content-members .splitcontentleft, div#tab-content-memberships .splitcontentleft, div#tab-content-users .splitcontentleft { width: 64% } +div#tab-content-members .splitcontentright, div#tab-content-memberships .splitcontentright, div#tab-content-users .splitcontentright { width: 34% } +div#tab-content-members fieldset, div#tab-content-memberships fieldset, div#tab-content-users fieldset { padding:1em; margin-bottom: 1em; } +div#tab-content-members fieldset legend, div#tab-content-memberships fieldset legend, div#tab-content-users fieldset legend { font-weight: bold; } +div#tab-content-members fieldset label, div#tab-content-memberships fieldset label, div#tab-content-users fieldset label { display: block; } +div#tab-content-members fieldset div, div#tab-content-users fieldset div { max-height: 400px; overflow:auto; } + +table.members td.group { padding-left: 20px; background: url(../images/group.png) no-repeat 0% 50%; } + +input#principal_search, input#user_search {width:100%} + +* html div#tab-content-members fieldset div { height: 450px; } + +/***** Flash & error messages ****/ +#errorExplanation, div.flash, .nodata, .warning { + padding: 4px 4px 4px 30px; + margin-bottom: 12px; + font-size: 1.1em; + border: 2px solid; +} + +div.flash {margin-top: 8px;} + +div.flash.error, #errorExplanation { + background: url(../images/exclamation.png) 8px 50% no-repeat; + background-color: #ffe3e3; + border-color: #dd0000; + color: #880000; +} + +div.flash.notice { + background: url(../images/true.png) 8px 5px no-repeat; + background-color: #dfffdf; + border-color: #9fcf9f; + color: #005f00; +} + +div.flash.warning { + background: url(../images/warning.png) 8px 5px no-repeat; + background-color: #FFEBC1; + border-color: #FDBF3B; + color: #A6750C; + text-align: left; +} + +.nodata, .warning { + text-align: center; + background-color: #FFEBC1; + border-color: #FDBF3B; + color: #A6750C; +} + +#errorExplanation ul { font-size: 0.9em;} +#errorExplanation h2, #errorExplanation p { display: none; } + +/***** Ajax indicator ******/ +#ajax-indicator { +position: absolute; /* fixed not supported by IE */ +background-color:#eee; +border: 1px solid #bbb; +top:35%; +left:40%; +width:20%; +font-weight:bold; +text-align:center; +padding:0.6em; +z-index:100; +filter:alpha(opacity=50); +opacity: 0.5; +} + +html>body #ajax-indicator { position: fixed; } + +#ajax-indicator span { +background-position: 0% 40%; +background-repeat: no-repeat; +background-image: url(../images/loading.gif); +padding-left: 26px; +vertical-align: bottom; +} + +/***** Calendar *****/ +table.cal {border-collapse: collapse; width: 100%; margin: 0px 0 6px 0;border: 1px solid #d7d7d7;} +table.cal thead th {width: 14%; background-color:#EEEEEE; padding: 4px; } +table.cal thead th.week-number {width: auto;} +table.cal tbody tr {height: 100px;} +table.cal td {border: 1px solid #d7d7d7; vertical-align: top; font-size: 0.9em;} +table.cal td.week-number { background-color:#EEEEEE; padding: 4px; border:none; font-size: 1em;} +table.cal td p.day-num {font-size: 1.1em; text-align:right;} +table.cal td.odd p.day-num {color: #bbb;} +table.cal td.today {background:#ffffdd;} +table.cal td.today p.day-num {font-weight: bold;} +table.cal .starting a, p.cal.legend .starting {background: url(../images/bullet_go.png) no-repeat -1px -2px; padding-left:16px;} +table.cal .ending a, p.cal.legend .ending {background: url(../images/bullet_end.png) no-repeat -1px -2px; padding-left:16px;} +table.cal .starting.ending a, p.cal.legend .starting.ending {background: url(../images/bullet_diamond.png) no-repeat -1px -2px; padding-left:16px;} +p.cal.legend span {display:block;} + +/***** Tooltips ******/ +.tooltip{position:relative;z-index:24;} +.tooltip:hover{z-index:25;color:#000;} +.tooltip span.tip{display: none; text-align:left;} + +div.tooltip:hover span.tip{ +display:block; +position:absolute; +top:12px; left:24px; width:270px; +border:1px solid #555; +background-color:#fff; +padding: 4px; +font-size: 0.8em; +color:#505050; +} + +/***** Progress bar *****/ +table.progress { + border: 1px solid #D7D7D7; + border-collapse: collapse; + border-spacing: 0pt; + empty-cells: show; + text-align: center; + float:left; + margin: 1px 6px 1px 0px; +} + +table.progress td { height: 0.9em; } +table.progress td.closed { background: #BAE0BA none repeat scroll 0%; } +table.progress td.done { background: #DEF0DE none repeat scroll 0%; } +table.progress td.open { background: #FFF none repeat scroll 0%; } +p.pourcent {font-size: 80%;} +p.progress-info {clear: left; font-style: italic; font-size: 80%;} + +/***** Tabs *****/ +#content .tabs {height: 2.6em; margin-bottom:1.2em; position:relative; overflow:hidden;} +#content .tabs ul {margin:0; position:absolute; bottom:0; padding-left:1em; width: 2000px; border-bottom: 1px solid #bbbbbb;} +#content .tabs ul li { +float:left; +list-style-type:none; +white-space:nowrap; +margin-right:8px; +background:#fff; +position:relative; +margin-bottom:-1px; +} +#content .tabs ul li a{ +display:block; +font-size: 0.9em; +text-decoration:none; +line-height:1.3em; +padding:4px 6px 4px 6px; +border: 1px solid #ccc; +border-bottom: 1px solid #bbbbbb; +background-color: #eeeeee; +color:#777; +font-weight:bold; +} + +#content .tabs ul li a:hover { +background-color: #ffffdd; +text-decoration:none; +} + +#content .tabs ul li a.selected { +background-color: #fff; +border: 1px solid #bbbbbb; +border-bottom: 1px solid #fff; +} + +#content .tabs ul li a.selected:hover { +background-color: #fff; +} + +div.tabs-buttons { position:absolute; right: 0; width: 48px; height: 24px; background: white; bottom: 0; border-bottom: 1px solid #bbbbbb; } + +button.tab-left, button.tab-right { + font-size: 0.9em; + cursor: pointer; + height:24px; + border: 1px solid #ccc; + border-bottom: 1px solid #bbbbbb; + position:absolute; + padding:4px; + width: 20px; + bottom: -1px; +} + +button.tab-left { + right: 20px; + background: #eeeeee url(../images/bullet_arrow_left.png) no-repeat 50% 50%; +} + +button.tab-right { + right: 0; + background: #eeeeee url(../images/bullet_arrow_right.png) no-repeat 50% 50%; +} + +/***** Auto-complete *****/ +div.autocomplete { + position:absolute; + width:400px; + margin:0; + padding:0; +} +div.autocomplete ul { + list-style-type:none; + margin:0; + padding:0; +} +div.autocomplete ul li { + list-style-type:none; + display:block; + margin:-1px 0 0 0; + padding:2px; + cursor:pointer; + font-size: 90%; + border: 1px solid #ccc; + border-left: 1px solid #ccc; + border-right: 1px solid #ccc; + background-color:white; +} +div.autocomplete ul li.selected { background-color: #ffb;} +div.autocomplete ul li span.informal { + font-size: 80%; + color: #aaa; +} + +#parent_issue_candidates ul li {width: 500px;} +#related_issue_candidates ul li {width: 500px;} + +/***** Diff *****/ +.diff_out { background: #fcc; } +.diff_in { background: #cfc; } + +/***** Wiki *****/ +div.wiki table { + border: 1px solid #505050; + border-collapse: collapse; + margin-bottom: 1em; +} + +div.wiki table, div.wiki td, div.wiki th { + border: 1px solid #bbb; + padding: 4px; +} + +div.wiki .external { + background-position: 0% 60%; + background-repeat: no-repeat; + padding-left: 12px; + background-image: url(../images/external.png); +} + +div.wiki a.new { + color: #b73535; +} + +div.wiki pre { + margin: 1em 1em 1em 1.6em; + padding: 2px 2px 2px 0; + background-color: #fafafa; + border: 1px solid #dadada; + width:auto; + overflow-x: auto; + overflow-y: hidden; +} + +div.wiki ul.toc { + background-color: #ffffdd; + border: 1px solid #e4e4e4; + padding: 4px; + line-height: 1.2em; + margin-bottom: 12px; + margin-right: 12px; + margin-left: 0; + display: table +} +* html div.wiki ul.toc { width: 50%; } /* IE6 doesn't autosize div */ + +div.wiki ul.toc.right { float: right; margin-left: 12px; margin-right: 0; width: auto; } +div.wiki ul.toc.left { float: left; margin-right: 12px; margin-left: 0; width: auto; } +div.wiki ul.toc ul { margin: 0; padding: 0; } +div.wiki ul.toc li { list-style-type:none; margin: 0;} +div.wiki ul.toc li li { margin-left: 1.5em; } +div.wiki ul.toc li li li { font-size: 0.8em; } + +div.wiki ul.toc a { + font-size: 0.9em; + font-weight: normal; + text-decoration: none; + color: #606060; +} +div.wiki ul.toc a:hover { color: #c61a1a; text-decoration: underline;} + +a.wiki-anchor { display: none; margin-left: 6px; text-decoration: none; } +a.wiki-anchor:hover { color: #aaa !important; text-decoration: none; } +h1:hover a.wiki-anchor, h2:hover a.wiki-anchor, h3:hover a.wiki-anchor { display: inline; color: #ddd; } + +div.wiki img { vertical-align: middle; } + +/***** My page layout *****/ +.block-receiver { +border:1px dashed #c0c0c0; +margin-bottom: 20px; +padding: 15px 0 15px 0; +} + +.mypage-box { +margin:0 0 20px 0; +color:#505050; +line-height:1.5em; +} + +.handle { +cursor: move; +} + +a.close-icon { +display:block; +margin-top:3px; +overflow:hidden; +width:12px; +height:12px; +background-repeat: no-repeat; +cursor:pointer; +background-image:url('../images/close.png'); +} + +a.close-icon:hover { +background-image:url('../images/close_hl.png'); +} + +/***** Gantt chart *****/ +.gantt_hdr { + position:absolute; + top:0; + height:16px; + border-top: 1px solid #c0c0c0; + border-bottom: 1px solid #c0c0c0; + border-right: 1px solid #c0c0c0; + text-align: center; + overflow: hidden; +} + +.gantt_subjects { font-size: 0.8em; } + +.task { + position: absolute; + height:8px; + font-size:0.8em; + color:#888; + padding:0; + margin:0; + line-height:0.8em; + white-space:nowrap; +} + +.task.label {width:100%;} +.task.label.project, .task.label.version { font-weight: bold; } + +.task_late { background:#f66 url(../images/task_late.png); border: 1px solid #f66; } +.task_done { background:#00c600 url(../images/task_done.png); border: 1px solid #00c600; } +.task_todo { background:#aaa url(../images/task_todo.png); border: 1px solid #aaa; } + +.task_todo.parent { background: #888; border: 1px solid #888; height: 3px;} +.task_late.parent, .task_done.parent { height: 3px;} +.task.parent.marker.starting { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-left: -4px; left: 0px; top: -1px;} +.task.parent.marker.ending { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-left: -4px; right: 0px; top: -1px;} + +.version.task_late { background:#f66 url(../images/milestone_late.png); border: 1px solid #f66; height: 2px; margin-top: 3px;} +.version.task_done { background:#00c600 url(../images/milestone_done.png); border: 1px solid #00c600; height: 2px; margin-top: 3px;} +.version.task_todo { background:#fff url(../images/milestone_todo.png); border: 1px solid #fff; height: 2px; margin-top: 3px;} +.version.marker { background-image:url(../images/version_marker.png); background-repeat: no-repeat; border: 0; margin-left: -4px; margin-top: 1px; } + +.project.task_late { background:#f66 url(../images/milestone_late.png); border: 1px solid #f66; height: 2px; margin-top: 3px;} +.project.task_done { background:#00c600 url(../images/milestone_done.png); border: 1px solid #00c600; height: 2px; margin-top: 3px;} +.project.task_todo { background:#fff url(../images/milestone_todo.png); border: 1px solid #fff; height: 2px; margin-top: 3px;} +.project.marker { background-image:url(../images/project_marker.png); background-repeat: no-repeat; border: 0; margin-left: -4px; margin-top: 1px; } + +.version-behind-schedule a, .issue-behind-schedule a {color: #f66914;} +.version-overdue a, .issue-overdue a, .project-overdue a {color: #f00;} + +/***** Icons *****/ +.icon { +background-position: 0% 50%; +background-repeat: no-repeat; +padding-left: 20px; +padding-top: 2px; +padding-bottom: 3px; +} + +.icon-add { background-image: url(../images/add.png); } +.icon-edit { background-image: url(../images/edit.png); } +.icon-copy { background-image: url(../images/copy.png); } +.icon-duplicate { background-image: url(../images/duplicate.png); } +.icon-del { background-image: url(../images/delete.png); } +.icon-move { background-image: url(../images/move.png); } +.icon-save { background-image: url(../images/save.png); } +.icon-cancel { background-image: url(../images/cancel.png); } +.icon-multiple { background-image: url(../images/table_multiple.png); } +.icon-folder { background-image: url(../images/folder.png); } +.open .icon-folder { background-image: url(../images/folder_open.png); } +.icon-package { background-image: url(../images/package.png); } +.icon-user { background-image: url(../images/user.png); } +.icon-projects { background-image: url(../images/projects.png); } +.icon-help { background-image: url(../images/help.png); } +.icon-attachment { background-image: url(../images/attachment.png); } +.icon-history { background-image: url(../images/history.png); } +.icon-time { background-image: url(../images/time.png); } +.icon-time-add { background-image: url(../images/time_add.png); } +.icon-stats { background-image: url(../images/stats.png); } +.icon-warning { background-image: url(../images/warning.png); } +.icon-fav { background-image: url(../images/fav.png); } +.icon-fav-off { background-image: url(../images/fav_off.png); } +.icon-reload { background-image: url(../images/reload.png); } +.icon-lock { background-image: url(../images/locked.png); } +.icon-unlock { background-image: url(../images/unlock.png); } +.icon-checked { background-image: url(../images/true.png); } +.icon-details { background-image: url(../images/zoom_in.png); } +.icon-report { background-image: url(../images/report.png); } +.icon-comment { background-image: url(../images/comment.png); } +.icon-summary { background-image: url(../images/lightning.png); } +.icon-server-authentication { background-image: url(../images/server_key.png); } +.icon-issue { background-image: url(../images/ticket.png); } +.icon-zoom-in { background-image: url(../images/zoom_in.png); } +.icon-zoom-out { background-image: url(../images/zoom_out.png); } + +.icon-file { background-image: url(../images/files/default.png); } +.icon-file.text-plain { background-image: url(../images/files/text.png); } +.icon-file.text-x-c { background-image: url(../images/files/c.png); } +.icon-file.text-x-csharp { background-image: url(../images/files/csharp.png); } +.icon-file.text-x-php { background-image: url(../images/files/php.png); } +.icon-file.text-x-ruby { background-image: url(../images/files/ruby.png); } +.icon-file.text-xml { background-image: url(../images/files/xml.png); } +.icon-file.image-gif { background-image: url(../images/files/image.png); } +.icon-file.image-jpeg { background-image: url(../images/files/image.png); } +.icon-file.image-png { background-image: url(../images/files/image.png); } +.icon-file.image-tiff { background-image: url(../images/files/image.png); } +.icon-file.application-pdf { background-image: url(../images/files/pdf.png); } +.icon-file.application-zip { background-image: url(../images/files/zip.png); } +.icon-file.application-x-gzip { background-image: url(../images/files/zip.png); } + +img.gravatar { + padding: 2px; + border: solid 1px #d5d5d5; + background: #fff; +} + +div.issue img.gravatar { + float: right; + margin: 0 0 0 1em; + padding: 5px; +} + +div.issue table img.gravatar { + height: 14px; + width: 14px; + padding: 2px; + float: left; + margin: 0 0.5em 0 0; +} + +h2 img.gravatar { + padding: 3px; + margin: -2px 4px -4px 0; + vertical-align: top; +} + +h4 img.gravatar { + padding: 3px; + margin: -6px 0 -4px 0; + vertical-align: top; +} + +td.username img.gravatar { + margin: 0 0.5em 0 0; + vertical-align: top; +} + +#activity dt img.gravatar { + float: left; + margin: 0 1em 1em 0; +} + +/* Used on 12px Gravatar img tags without the icon background */ +.icon-gravatar { + float: left; + margin-right: 4px; +} + +#activity dt, +.journal { + clear: left; +} + +.journal-link { + float: right; +} + +h2 img { vertical-align:middle; } + +.hascontextmenu { cursor: context-menu; } + +/***** Media print specific styles *****/ +@media print { + #top-menu, #header, #main-menu, #sidebar, #footer, .contextual, .other-formats { display:none; } + #main { background: #fff; } + #content { width: 99%; margin: 0; padding: 0; border: 0; background: #fff; overflow: visible !important;} + #wiki_add_attachment { display:none; } + .hide-when-print { display: none; } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/public/stylesheets/.svn/tmp/tempfile.tmp Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,951 @@ +html {overflow-y:scroll;} +body { font-family: Verdana, sans-serif; font-size: 12px; color:#484848; margin: 0; padding: 0; min-width: 900px; } + +h1, h2, h3, h4 { font-family: "Trebuchet MS", Verdana, sans-serif;} +h1 {margin:0; padding:0; font-size: 24px;} +h2, .wiki h1 {font-size: 20px;padding: 2px 10px 1px 0px;margin: 0 0 10px 0; border-bottom: 1px solid #bbbbbb; color: #444;} +h3, .wiki h2 {font-size: 16px;padding: 2px 10px 1px 0px;margin: 0 0 10px 0; border-bottom: 1px solid #bbbbbb; color: #444;} +h4, .wiki h3 {font-size: 13px;padding: 2px 10px 1px 0px;margin-bottom: 5px; border-bottom: 1px dotted #bbbbbb; color: #444;} + +/***** Layout *****/ +#wrapper {background: white;} + +#top-menu {background: #2C4056; color: #fff; height:1.8em; font-size: 0.8em; padding: 2px 2px 0px 6px;} +#top-menu ul {margin: 0; padding: 0;} +#top-menu li { + float:left; + list-style-type:none; + margin: 0px 0px 0px 0px; + padding: 0px 0px 0px 0px; + white-space:nowrap; +} +#top-menu a {color: #fff; margin-right: 8px; font-weight: bold;} +#top-menu #loggedas { float: right; margin-right: 0.5em; color: #fff; } + +#account {float:right;} + +#header {height:5.3em;margin:0;background-color:#507AAA;color:#f8f8f8; padding: 4px 8px 0px 6px; position:relative;} +#header a {color:#f8f8f8;} +#header h1 a.ancestor { font-size: 80%; } +#quick-search {float:right;} + +#main-menu {position: absolute; bottom: 0px; left:6px; margin-right: -500px;} +#main-menu ul {margin: 0; padding: 0;} +#main-menu li { + float:left; + list-style-type:none; + margin: 0px 2px 0px 0px; + padding: 0px 0px 0px 0px; + white-space:nowrap; +} +#main-menu li a { + display: block; + color: #fff; + text-decoration: none; + font-weight: bold; + margin: 0; + padding: 4px 10px 4px 10px; +} +#main-menu li a:hover {background:#759FCF; color:#fff;} +#main-menu li a.selected, #main-menu li a.selected:hover {background:#fff; color:#555;} + +#admin-menu ul {margin: 0; padding: 0;} +#admin-menu li {margin: 0; padding: 0 0 12px 0; list-style-type:none;} + +#admin-menu a { background-position: 0% 40%; background-repeat: no-repeat; padding-left: 20px; padding-top: 2px; padding-bottom: 3px;} +#admin-menu a.projects { background-image: url(../images/projects.png); } +#admin-menu a.users { background-image: url(../images/user.png); } +#admin-menu a.groups { background-image: url(../images/group.png); } +#admin-menu a.roles { background-image: url(../images/database_key.png); } +#admin-menu a.trackers { background-image: url(../images/ticket.png); } +#admin-menu a.issue_statuses { background-image: url(../images/ticket_edit.png); } +#admin-menu a.workflows { background-image: url(../images/ticket_go.png); } +#admin-menu a.custom_fields { background-image: url(../images/textfield.png); } +#admin-menu a.enumerations { background-image: url(../images/text_list_bullets.png); } +#admin-menu a.settings { background-image: url(../images/changeset.png); } +#admin-menu a.plugins { background-image: url(../images/plugin.png); } +#admin-menu a.info { background-image: url(../images/help.png); } +#admin-menu a.server_authentication { background-image: url(../images/server_key.png); } + +#main {background-color:#EEEEEE;} + +#sidebar{ float: right; width: 22%; position: relative; z-index: 9; padding: 0; margin: 0;} +* html #sidebar{ width: 22%; } +#sidebar h3{ font-size: 14px; margin-top:14px; color: #666; } +#sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; } +* html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; } +#sidebar .contextual { margin-right: 1em; } + +#content { width: 75%; background-color: #fff; margin: 0px; border-right: 1px solid #ddd; padding: 6px 10px 10px 10px; z-index: 10; } +* html #content{ width: 75%; padding-left: 0; margin-top: 0px; padding: 6px 10px 10px 10px;} +html>body #content { min-height: 600px; } +* html body #content { height: 600px; } /* IE */ + +#main.nosidebar #sidebar{ display: none; } +#main.nosidebar #content{ width: auto; border-right: 0; } + +#footer {clear: both; border-top: 1px solid #bbb; font-size: 0.9em; color: #aaa; padding: 5px; text-align:center; background:#fff;} + +#login-form table {margin-top:5em; padding:1em; margin-left: auto; margin-right: auto; border: 2px solid #FDBF3B; background-color:#FFEBC1; } +#login-form table td {padding: 6px;} +#login-form label {font-weight: bold;} +#login-form input#username, #login-form input#password { width: 300px; } + +input#openid_url { background: url(../images/openid-bg.gif) no-repeat; background-color: #fff; background-position: 0 50%; padding-left: 18px; } + +.clear:after{ content: "."; display: block; height: 0; clear: both; visibility: hidden; } + +/***** Links *****/ +a, a:link, a:visited{ color: #2A5685; text-decoration: none; } +a:hover, a:active{ color: #c61a1a; text-decoration: underline;} +a img{ border: 0; } + +a.issue.closed, a.issue.closed:link, a.issue.closed:visited { color: #999; text-decoration: line-through; } + +/***** Tables *****/ +table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; } +table.list th { background-color:#EEEEEE; padding: 4px; white-space:nowrap; } +table.list td { vertical-align: top; } +table.list td.id { width: 2%; text-align: center;} +table.list td.checkbox { width: 15px; padding: 0px;} +table.list td.buttons { width: 15%; white-space:nowrap; text-align: right; } +table.list td.buttons a { padding-right: 0.6em; } +table.list caption { text-align: left; padding: 0.5em 0.5em 0.5em 0; } + +tr.project td.name a { white-space:nowrap; } + +tr.project.idnt td.name span {background: url(../images/bullet_arrow_right.png) no-repeat 0 50%; padding-left: 16px;} +tr.project.idnt-1 td.name {padding-left: 0.5em;} +tr.project.idnt-2 td.name {padding-left: 2em;} +tr.project.idnt-3 td.name {padding-left: 3.5em;} +tr.project.idnt-4 td.name {padding-left: 5em;} +tr.project.idnt-5 td.name {padding-left: 6.5em;} +tr.project.idnt-6 td.name {padding-left: 8em;} +tr.project.idnt-7 td.name {padding-left: 9.5em;} +tr.project.idnt-8 td.name {padding-left: 11em;} +tr.project.idnt-9 td.name {padding-left: 12.5em;} + +tr.issue { text-align: center; white-space: nowrap; } +tr.issue td.subject, tr.issue td.category, td.assigned_to { white-space: normal; } +tr.issue td.subject { text-align: left; } +tr.issue td.done_ratio table.progress { margin-left:auto; margin-right: auto;} + +tr.issue.idnt td.subject a {background: url(../images/bullet_arrow_right.png) no-repeat 0 50%; padding-left: 16px;} +tr.issue.idnt-1 td.subject {padding-left: 0.5em;} +tr.issue.idnt-2 td.subject {padding-left: 2em;} +tr.issue.idnt-3 td.subject {padding-left: 3.5em;} +tr.issue.idnt-4 td.subject {padding-left: 5em;} +tr.issue.idnt-5 td.subject {padding-left: 6.5em;} +tr.issue.idnt-6 td.subject {padding-left: 8em;} +tr.issue.idnt-7 td.subject {padding-left: 9.5em;} +tr.issue.idnt-8 td.subject {padding-left: 11em;} +tr.issue.idnt-9 td.subject {padding-left: 12.5em;} + +tr.entry { border: 1px solid #f8f8f8; } +tr.entry td { white-space: nowrap; } +tr.entry td.filename { width: 30%; } +tr.entry td.size { text-align: right; font-size: 90%; } +tr.entry td.revision, tr.entry td.author { text-align: center; } +tr.entry td.age { text-align: right; } +tr.entry.file td.filename a { margin-left: 16px; } + +tr span.expander {background-image: url(../images/bullet_toggle_plus.png); padding-left: 8px; margin-left: 0; cursor: pointer;} +tr.open span.expander {background-image: url(../images/bullet_toggle_minus.png);} + +tr.changeset td.author { text-align: center; width: 15%; } +tr.changeset td.committed_on { text-align: center; width: 15%; } + +table.files tr.file td { text-align: center; } +table.files tr.file td.filename { text-align: left; padding-left: 24px; } +table.files tr.file td.digest { font-size: 80%; } + +table.members td.roles, table.memberships td.roles { width: 45%; } + +tr.message { height: 2.6em; } +tr.message td.subject { padding-left: 20px; } +tr.message td.created_on { white-space: nowrap; } +tr.message td.last_message { font-size: 80%; white-space: nowrap; } +tr.message.locked td.subject { background: url(../images/locked.png) no-repeat 0 1px; } +tr.message.sticky td.subject { background: url(../images/bullet_go.png) no-repeat 0 1px; font-weight: bold; } + +tr.version.closed, tr.version.closed a { color: #999; } +tr.version td.name { padding-left: 20px; } +tr.version.shared td.name { background: url(../images/link.png) no-repeat 0% 70%; } +tr.version td.date, tr.version td.status, tr.version td.sharing { text-align: center; } + +tr.user td { width:13%; } +tr.user td.email { width:18%; } +tr.user td { white-space: nowrap; } +tr.user.locked, tr.user.registered { color: #aaa; } +tr.user.locked a, tr.user.registered a { color: #aaa; } + +tr.wiki-page-version td.updated_on, tr.wiki-page-version td.author {text-align:center;} + +tr.time-entry { text-align: center; white-space: nowrap; } +tr.time-entry td.subject, tr.time-entry td.comments { text-align: left; white-space: normal; } +td.hours { text-align: right; font-weight: bold; padding-right: 0.5em; } +td.hours .hours-dec { font-size: 0.9em; } + +table.plugins td { vertical-align: middle; } +table.plugins td.configure { text-align: right; padding-right: 1em; } +table.plugins span.name { font-weight: bold; display: block; margin-bottom: 6px; } +table.plugins span.description { display: block; font-size: 0.9em; } +table.plugins span.url { display: block; font-size: 0.9em; } + +table.list tbody tr.group td { padding: 0.8em 0 0.5em 0.3em; font-weight: bold; border-bottom: 1px solid #ccc; } +table.list tbody tr.group span.count { color: #aaa; font-size: 80%; } + +table.list tbody tr:hover { background-color:#ffffdd; } +table.list tbody tr.group:hover { background-color:inherit; } +table td {padding:2px;} +table p {margin:0;} +.odd {background-color:#f6f7f8;} +.even {background-color: #fff;} + +a.sort { padding-right: 16px; background-position: 100% 50%; background-repeat: no-repeat; } +a.sort.asc { background-image: url(../images/sort_asc.png); } +a.sort.desc { background-image: url(../images/sort_desc.png); } + +table.attributes { width: 100% } +table.attributes th { vertical-align: top; text-align: left; } +table.attributes td { vertical-align: top; } + +table.boards a.board, h3.comments { background: url(../images/comment.png) no-repeat 0% 50%; padding-left: 20px; } + +td.center {text-align:center;} + +h3.version { background: url(../images/package.png) no-repeat 0% 50%; padding-left: 20px; } + +div.issues h3 { background: url(../images/ticket.png) no-repeat 0% 50%; padding-left: 20px; } +div.members h3 { background: url(../images/group.png) no-repeat 0% 50%; padding-left: 20px; } +div.news h3 { background: url(../images/news.png) no-repeat 0% 50%; padding-left: 20px; } +div.projects h3 { background: url(../images/projects.png) no-repeat 0% 50%; padding-left: 20px; } + +#watchers ul {margin: 0; padding: 0;} +#watchers li {list-style-type:none;margin: 0px 2px 0px 0px; padding: 0px 0px 0px 0px;} +#watchers select {width: 95%; display: block;} +#watchers a.delete {opacity: 0.4;} +#watchers a.delete:hover {opacity: 1;} +#watchers img.gravatar {vertical-align: middle;margin: 0 4px 2px 0;} + +.highlight { background-color: #FCFD8D;} +.highlight.token-1 { background-color: #faa;} +.highlight.token-2 { background-color: #afa;} +.highlight.token-3 { background-color: #aaf;} + +.box{ +padding:6px; +margin-bottom: 10px; +background-color:#f6f6f6; +color:#505050; +line-height:1.5em; +border: 1px solid #e4e4e4; +} + +div.square { + border: 1px solid #999; + float: left; + margin: .3em .4em 0 .4em; + overflow: hidden; + width: .6em; height: .6em; +} +.contextual {float:right; white-space: nowrap; line-height:1.4em;margin-top:5px; padding-left: 10px; font-size:0.9em;} +.contextual input, .contextual select {font-size:0.9em;} +.message .contextual { margin-top: 0; } + +.splitcontentleft{float:left; width:49%;} +.splitcontentright{float:right; width:49%;} +form {display: inline;} +input, select {vertical-align: middle; margin-top: 1px; margin-bottom: 1px;} +fieldset {border: 1px solid #e4e4e4; margin:0;} +legend {color: #484848;} +hr { width: 100%; height: 1px; background: #ccc; border: 0;} +blockquote { font-style: italic; border-left: 3px solid #e0e0e0; padding-left: 0.6em; margin-left: 2.4em;} +blockquote blockquote { margin-left: 0;} +acronym { border-bottom: 1px dotted; cursor: help; } +textarea.wiki-edit { width: 99%; } +li p {margin-top: 0;} +div.issue {background:#ffffdd; padding:6px; margin-bottom:6px;border: 1px solid #d7d7d7;} +p.breadcrumb { font-size: 0.9em; margin: 4px 0 4px 0;} +p.subtitle { font-size: 0.9em; margin: -6px 0 12px 0; font-style: italic; } +p.footnote { font-size: 0.9em; margin-top: 0px; margin-bottom: 0px; } + +div.issue div.subject div div { padding-left: 16px; } +div.issue div.subject p {margin: 0; margin-bottom: 0.1em; font-size: 90%; color: #999;} +div.issue div.subject>div>p { margin-top: 0.5em; } +div.issue div.subject h3 {margin: 0; margin-bottom: 0.1em;} + +#issue_tree table.issues { border: 0; } +#issue_tree td.checkbox {display:none;} + +fieldset.collapsible { border-width: 1px 0 0 0; font-size: 0.9em; } +fieldset.collapsible legend { padding-left: 16px; background: url(../images/arrow_expanded.png) no-repeat 0% 40%; cursor:pointer; } +fieldset.collapsible.collapsed legend { background-image: url(../images/arrow_collapsed.png); } + +fieldset#date-range p { margin: 2px 0 2px 0; } +fieldset#filters table { border-collapse: collapse; } +fieldset#filters table td { padding: 0; vertical-align: middle; } +fieldset#filters tr.filter { height: 2em; } +fieldset#filters td.add-filter { text-align: right; vertical-align: top; } +.buttons { font-size: 0.9em; margin-bottom: 1.4em; margin-top: 1em; } + +div#issue-changesets {float:right; width:45%; margin-left: 1em; margin-bottom: 1em; background: #fff; padding-left: 1em; font-size: 90%;} +div#issue-changesets div.changeset { padding: 4px;} +div#issue-changesets div.changeset { border-bottom: 1px solid #ddd; } +div#issue-changesets p { margin-top: 0; margin-bottom: 1em;} + +div#activity dl, #search-results { margin-left: 2em; } +div#activity dd, #search-results dd { margin-bottom: 1em; padding-left: 18px; font-size: 0.9em; } +div#activity dt, #search-results dt { margin-bottom: 0px; padding-left: 20px; line-height: 18px; background-position: 0 50%; background-repeat: no-repeat; } +div#activity dt.me .time { border-bottom: 1px solid #999; } +div#activity dt .time { color: #777; font-size: 80%; } +div#activity dd .description, #search-results dd .description { font-style: italic; } +div#activity span.project:after, #search-results span.project:after { content: " -"; } +div#activity dd span.description, #search-results dd span.description { display:block; color: #808080; } + +#search-results dd { margin-bottom: 1em; padding-left: 20px; margin-left:0px; } + +div#search-results-counts {float:right;} +div#search-results-counts ul { margin-top: 0.5em; } +div#search-results-counts li { list-style-type:none; float: left; margin-left: 1em; } + +dt.issue { background-image: url(../images/ticket.png); } +dt.issue-edit { background-image: url(../images/ticket_edit.png); } +dt.issue-closed { background-image: url(../images/ticket_checked.png); } +dt.issue-note { background-image: url(../images/ticket_note.png); } +dt.changeset { background-image: url(../images/changeset.png); } +dt.news { background-image: url(../images/news.png); } +dt.message { background-image: url(../images/message.png); } +dt.reply { background-image: url(../images/comments.png); } +dt.wiki-page { background-image: url(../images/wiki_edit.png); } +dt.attachment { background-image: url(../images/attachment.png); } +dt.document { background-image: url(../images/document.png); } +dt.project { background-image: url(../images/projects.png); } +dt.time-entry { background-image: url(../images/time.png); } + +#search-results dt.issue.closed { background-image: url(../images/ticket_checked.png); } + +div#roadmap .related-issues { margin-bottom: 1em; } +div#roadmap .related-issues td.checkbox { display: none; } +div#roadmap .wiki h1:first-child { display: none; } +div#roadmap .wiki h1 { font-size: 120%; } +div#roadmap .wiki h2 { font-size: 110%; } + +div#version-summary { float:right; width:380px; margin-left: 16px; margin-bottom: 16px; background-color: #fff; } +div#version-summary fieldset { margin-bottom: 1em; } +div#version-summary .total-hours { text-align: right; } + +table#time-report td.hours, table#time-report th.period, table#time-report th.total { text-align: right; padding-right: 0.5em; } +table#time-report tbody tr { font-style: italic; color: #777; } +table#time-report tbody tr.last-level { font-style: normal; color: #555; } +table#time-report tbody tr.total { font-style: normal; font-weight: bold; color: #555; background-color:#EEEEEE; } +table#time-report .hours-dec { font-size: 0.9em; } + +form .attributes { margin-bottom: 8px; } +form .attributes p { padding-top: 1px; padding-bottom: 2px; } +form .attributes select { min-width: 50%; } + +ul.projects { margin: 0; padding-left: 1em; } +ul.projects.root { margin: 0; padding: 0; } +ul.projects ul.projects { border-left: 3px solid #e0e0e0; } +ul.projects li.root { list-style-type:none; margin-bottom: 1em; } +ul.projects li.child { list-style-type:none; margin-top: 1em;} +ul.projects div.root a.project { /* font-family: "Trebuchet MS", Verdana, sans-serif; */ font-weight: bold; font-size: 16px; margin: 0 0 10px 0; } +.my-project { padding-left: 18px; background: url(../images/fav.png) no-repeat 0 50%; } + +#tracker_project_ids ul { margin: 0; padding-left: 1em; } +#tracker_project_ids li { list-style-type:none; } + +ul.properties {padding:0; font-size: 0.9em; color: #777;} +ul.properties li {list-style-type:none;} +ul.properties li span {font-style:italic;} + +.total-hours { font-size: 110%; font-weight: bold; } +.total-hours span.hours-int { font-size: 120%; } + +.autoscroll {overflow-x: auto; padding:1px; margin-bottom: 1.2em;} +#user_firstname, #user_lastname, #user_mail, #my_account_form select { width: 90%; } + +#workflow_copy_form select { width: 200px; } + +.pagination {font-size: 90%} +p.pagination {margin-top:8px;} + +/***** Tabular forms ******/ +.tabular p{ +margin: 0; +padding: 5px 0 8px 0; +padding-left: 180px; /*width of left column containing the label elements*/ +height: 1%; +clear:left; +} + +html>body .tabular p {overflow:hidden;} + +.tabular label{ +font-weight: bold; +float: left; +text-align: right; +margin-left: -180px; /*width of left column*/ +width: 175px; /*width of labels. Should be smaller than left column to create some right +margin*/ +} + +.tabular label.floating{ +font-weight: normal; +margin-left: 0px; +text-align: left; +width: 270px; +} + +.tabular label.block{ +font-weight: normal; +margin-left: 0px !important; +text-align: left; +float: none; +display: block; +width: auto; +} + +.tabular label.inline{ +float:none; +margin-left: 5px !important; +width: auto; +} + +input#time_entry_comments { width: 90%;} + +#preview fieldset {margin-top: 1em; background: url(../images/draft.png)} + +.tabular.settings p{ padding-left: 300px; } +.tabular.settings label{ margin-left: -300px; width: 295px; } +.tabular.settings textarea { width: 99%; } + +fieldset.settings label { display: block; } +.parent { padding-left: 20px; } + +.required {color: #bb0000;} +.summary {font-style: italic;} + +#attachments_fields input[type=text] {margin-left: 8px; } + +div.attachments { margin-top: 12px; } +div.attachments p { margin:4px 0 2px 0; } +div.attachments img { vertical-align: middle; } +div.attachments span.author { font-size: 0.9em; color: #888; } + +p.other-formats { text-align: right; font-size:0.9em; color: #666; } +.other-formats span + span:before { content: "| "; } + +a.atom { background: url(../images/feed.png) no-repeat 1px 50%; padding: 2px 0px 3px 16px; } + +/* Project members tab */ +div#tab-content-members .splitcontentleft, div#tab-content-memberships .splitcontentleft, div#tab-content-users .splitcontentleft { width: 64% } +div#tab-content-members .splitcontentright, div#tab-content-memberships .splitcontentright, div#tab-content-users .splitcontentright { width: 34% } +div#tab-content-members fieldset, div#tab-content-memberships fieldset, div#tab-content-users fieldset { padding:1em; margin-bottom: 1em; } +div#tab-content-members fieldset legend, div#tab-content-memberships fieldset legend, div#tab-content-users fieldset legend { font-weight: bold; } +div#tab-content-members fieldset label, div#tab-content-memberships fieldset label, div#tab-content-users fieldset label { display: block; } +div#tab-content-members fieldset div, div#tab-content-users fieldset div { max-height: 400px; overflow:auto; } + +table.members td.group { padding-left: 20px; background: url(../images/group.png) no-repeat 0% 50%; } + +input#principal_search, input#user_search {width:100%} + +* html div#tab-content-members fieldset div { height: 450px; } + +/***** Flash & error messages ****/ +#errorExplanation, div.flash, .nodata, .warning { + padding: 4px 4px 4px 30px; + margin-bottom: 12px; + font-size: 1.1em; + border: 2px solid; +} + +div.flash {margin-top: 8px;} + +div.flash.error, #errorExplanation { + background: url(../images/exclamation.png) 8px 50% no-repeat; + background-color: #ffe3e3; + border-color: #dd0000; + color: #880000; +} + +div.flash.notice { + background: url(../images/true.png) 8px 5px no-repeat; + background-color: #dfffdf; + border-color: #9fcf9f; + color: #005f00; +} + +div.flash.warning { + background: url(../images/warning.png) 8px 5px no-repeat; + background-color: #FFEBC1; + border-color: #FDBF3B; + color: #A6750C; + text-align: left; +} + +.nodata, .warning { + text-align: center; + background-color: #FFEBC1; + border-color: #FDBF3B; + color: #A6750C; +} + +#errorExplanation ul { font-size: 0.9em;} +#errorExplanation h2, #errorExplanation p { display: none; } + +/***** Ajax indicator ******/ +#ajax-indicator { +position: absolute; /* fixed not supported by IE */ +background-color:#eee; +border: 1px solid #bbb; +top:35%; +left:40%; +width:20%; +font-weight:bold; +text-align:center; +padding:0.6em; +z-index:100; +filter:alpha(opacity=50); +opacity: 0.5; +} + +html>body #ajax-indicator { position: fixed; } + +#ajax-indicator span { +background-position: 0% 40%; +background-repeat: no-repeat; +background-image: url(../images/loading.gif); +padding-left: 26px; +vertical-align: bottom; +} + +/***** Calendar *****/ +table.cal {border-collapse: collapse; width: 100%; margin: 0px 0 6px 0;border: 1px solid #d7d7d7;} +table.cal thead th {width: 14%; background-color:#EEEEEE; padding: 4px; } +table.cal thead th.week-number {width: auto;} +table.cal tbody tr {height: 100px;} +table.cal td {border: 1px solid #d7d7d7; vertical-align: top; font-size: 0.9em;} +table.cal td.week-number { background-color:#EEEEEE; padding: 4px; border:none; font-size: 1em;} +table.cal td p.day-num {font-size: 1.1em; text-align:right;} +table.cal td.odd p.day-num {color: #bbb;} +table.cal td.today {background:#ffffdd;} +table.cal td.today p.day-num {font-weight: bold;} +table.cal .starting a, p.cal.legend .starting {background: url(../images/bullet_go.png) no-repeat -1px -2px; padding-left:16px;} +table.cal .ending a, p.cal.legend .ending {background: url(../images/bullet_end.png) no-repeat -1px -2px; padding-left:16px;} +table.cal .starting.ending a, p.cal.legend .starting.ending {background: url(../images/bullet_diamond.png) no-repeat -1px -2px; padding-left:16px;} +p.cal.legend span {display:block;} + +/***** Tooltips ******/ +.tooltip{position:relative;z-index:24;} +.tooltip:hover{z-index:25;color:#000;} +.tooltip span.tip{display: none; text-align:left;} + +div.tooltip:hover span.tip{ +display:block; +position:absolute; +top:12px; left:24px; width:270px; +border:1px solid #555; +background-color:#fff; +padding: 4px; +font-size: 0.8em; +color:#505050; +} + +/***** Progress bar *****/ +table.progress { + border: 1px solid #D7D7D7; + border-collapse: collapse; + border-spacing: 0pt; + empty-cells: show; + text-align: center; + float:left; + margin: 1px 6px 1px 0px; +} + +table.progress td { height: 0.9em; } +table.progress td.closed { background: #BAE0BA none repeat scroll 0%; } +table.progress td.done { background: #DEF0DE none repeat scroll 0%; } +table.progress td.open { background: #FFF none repeat scroll 0%; } +p.pourcent {font-size: 80%;} +p.progress-info {clear: left; font-style: italic; font-size: 80%;} + +/***** Tabs *****/ +#content .tabs {height: 2.6em; margin-bottom:1.2em; position:relative; overflow:hidden;} +#content .tabs ul {margin:0; position:absolute; bottom:0; padding-left:1em; width: 2000px; border-bottom: 1px solid #bbbbbb;} +#content .tabs ul li { +float:left; +list-style-type:none; +white-space:nowrap; +margin-right:8px; +background:#fff; +position:relative; +margin-bottom:-1px; +} +#content .tabs ul li a{ +display:block; +font-size: 0.9em; +text-decoration:none; +line-height:1.3em; +padding:4px 6px 4px 6px; +border: 1px solid #ccc; +border-bottom: 1px solid #bbbbbb; +background-color: #eeeeee; +color:#777; +font-weight:bold; +} + +#content .tabs ul li a:hover { +background-color: #ffffdd; +text-decoration:none; +} + +#content .tabs ul li a.selected { +background-color: #fff; +border: 1px solid #bbbbbb; +border-bottom: 1px solid #fff; +} + +#content .tabs ul li a.selected:hover { +background-color: #fff; +} + +div.tabs-buttons { position:absolute; right: 0; width: 48px; height: 24px; background: white; bottom: 0; border-bottom: 1px solid #bbbbbb; } + +button.tab-left, button.tab-right { + font-size: 0.9em; + cursor: pointer; + height:24px; + border: 1px solid #ccc; + border-bottom: 1px solid #bbbbbb; + position:absolute; + padding:4px; + width: 20px; + bottom: -1px; +} + +button.tab-left { + right: 20px; + background: #eeeeee url(../images/bullet_arrow_left.png) no-repeat 50% 50%; +} + +button.tab-right { + right: 0; + background: #eeeeee url(../images/bullet_arrow_right.png) no-repeat 50% 50%; +} + +/***** Auto-complete *****/ +div.autocomplete { + position:absolute; + width:400px; + margin:0; + padding:0; +} +div.autocomplete ul { + list-style-type:none; + margin:0; + padding:0; +} +div.autocomplete ul li { + list-style-type:none; + display:block; + margin:-1px 0 0 0; + padding:2px; + cursor:pointer; + font-size: 90%; + border: 1px solid #ccc; + border-left: 1px solid #ccc; + border-right: 1px solid #ccc; + background-color:white; +} +div.autocomplete ul li.selected { background-color: #ffb;} +div.autocomplete ul li span.informal { + font-size: 80%; + color: #aaa; +} + +#parent_issue_candidates ul li {width: 500px;} +#related_issue_candidates ul li {width: 500px;} + +/***** Diff *****/ +.diff_out { background: #fcc; } +.diff_in { background: #cfc; } + +/***** Wiki *****/ +div.wiki table { + border: 1px solid #505050; + border-collapse: collapse; + margin-bottom: 1em; +} + +div.wiki table, div.wiki td, div.wiki th { + border: 1px solid #bbb; + padding: 4px; +} + +div.wiki .external { + background-position: 0% 60%; + background-repeat: no-repeat; + padding-left: 12px; + background-image: url(../images/external.png); +} + +div.wiki a.new { + color: #b73535; +} + +div.wiki pre { + margin: 1em 1em 1em 1.6em; + padding: 2px 2px 2px 0; + background-color: #fafafa; + border: 1px solid #dadada; + width:auto; + overflow-x: auto; + overflow-y: hidden; +} + +div.wiki ul.toc { + background-color: #ffffdd; + border: 1px solid #e4e4e4; + padding: 4px; + line-height: 1.2em; + margin-bottom: 12px; + margin-right: 12px; + margin-left: 0; + display: table +} +* html div.wiki ul.toc { width: 50%; } /* IE6 doesn't autosize div */ + +div.wiki ul.toc.right { float: right; margin-left: 12px; margin-right: 0; width: auto; } +div.wiki ul.toc.left { float: left; margin-right: 12px; margin-left: 0; width: auto; } +div.wiki ul.toc ul { margin: 0; padding: 0; } +div.wiki ul.toc li { list-style-type:none; margin: 0;} +div.wiki ul.toc li li { margin-left: 1.5em; } +div.wiki ul.toc li li li { font-size: 0.8em; } + +div.wiki ul.toc a { + font-size: 0.9em; + font-weight: normal; + text-decoration: none; + color: #606060; +} +div.wiki ul.toc a:hover { color: #c61a1a; text-decoration: underline;} + +a.wiki-anchor { display: none; margin-left: 6px; text-decoration: none; } +a.wiki-anchor:hover { color: #aaa !important; text-decoration: none; } +h1:hover a.wiki-anchor, h2:hover a.wiki-anchor, h3:hover a.wiki-anchor { display: inline; color: #ddd; } + +div.wiki img { vertical-align: middle; } + +/***** My page layout *****/ +.block-receiver { +border:1px dashed #c0c0c0; +margin-bottom: 20px; +padding: 15px 0 15px 0; +} + +.mypage-box { +margin:0 0 20px 0; +color:#505050; +line-height:1.5em; +} + +.handle { +cursor: move; +} + +a.close-icon { +display:block; +margin-top:3px; +overflow:hidden; +width:12px; +height:12px; +background-repeat: no-repeat; +cursor:pointer; +background-image:url('../images/close.png'); +} + +a.close-icon:hover { +background-image:url('../images/close_hl.png'); +} + +/***** Gantt chart *****/ +.gantt_hdr { + position:absolute; + top:0; + height:16px; + border-top: 1px solid #c0c0c0; + border-bottom: 1px solid #c0c0c0; + border-right: 1px solid #c0c0c0; + text-align: center; + overflow: hidden; +} + +.gantt_subjects { font-size: 0.8em; } + +.task { + position: absolute; + height:8px; + font-size:0.8em; + color:#888; + padding:0; + margin:0; + line-height:0.8em; + white-space:nowrap; +} + +.task.label {width:100%;} +.task.label.project, .task.label.version { font-weight: bold; } + +.task_late { background:#f66 url(../images/task_late.png); border: 1px solid #f66; } +.task_done { background:#00c600 url(../images/task_done.png); border: 1px solid #00c600; } +.task_todo { background:#aaa url(../images/task_todo.png); border: 1px solid #aaa; } + +.task_todo.parent { background: #888; border: 1px solid #888; height: 3px;} +.task_late.parent, .task_done.parent { height: 3px;} +.task.parent.marker.starting { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-left: -4px; left: 0px; top: -1px;} +.task.parent.marker.ending { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-left: -4px; right: 0px; top: -1px;} + +.version.task_late { background:#f66 url(../images/milestone_late.png); border: 1px solid #f66; height: 2px; margin-top: 3px;} +.version.task_done { background:#00c600 url(../images/milestone_done.png); border: 1px solid #00c600; height: 2px; margin-top: 3px;} +.version.task_todo { background:#fff url(../images/milestone_todo.png); border: 1px solid #fff; height: 2px; margin-top: 3px;} +.version.marker { background-image:url(../images/version_marker.png); background-repeat: no-repeat; border: 0; margin-left: -4px; margin-top: 1px; } + +.project.task_late { background:#f66 url(../images/milestone_late.png); border: 1px solid #f66; height: 2px; margin-top: 3px;} +.project.task_done { background:#00c600 url(../images/milestone_done.png); border: 1px solid #00c600; height: 2px; margin-top: 3px;} +.project.task_todo { background:#fff url(../images/milestone_todo.png); border: 1px solid #fff; height: 2px; margin-top: 3px;} +.project.marker { background-image:url(../images/project_marker.png); background-repeat: no-repeat; border: 0; margin-left: -4px; margin-top: 1px; } + +.version-behind-schedule a, .issue-behind-schedule a {color: #f66914;} +.version-overdue a, .issue-overdue a, .project-overdue a {color: #f00;} + +/***** Icons *****/ +.icon { +background-position: 0% 50%; +background-repeat: no-repeat; +padding-left: 20px; +padding-top: 2px; +padding-bottom: 3px; +} + +.icon-add { background-image: url(../images/add.png); } +.icon-edit { background-image: url(../images/edit.png); } +.icon-copy { background-image: url(../images/copy.png); } +.icon-duplicate { background-image: url(../images/duplicate.png); } +.icon-del { background-image: url(../images/delete.png); } +.icon-move { background-image: url(../images/move.png); } +.icon-save { background-image: url(../images/save.png); } +.icon-cancel { background-image: url(../images/cancel.png); } +.icon-multiple { background-image: url(../images/table_multiple.png); } +.icon-folder { background-image: url(../images/folder.png); } +.open .icon-folder { background-image: url(../images/folder_open.png); } +.icon-package { background-image: url(../images/package.png); } +.icon-user { background-image: url(../images/user.png); } +.icon-projects { background-image: url(../images/projects.png); } +.icon-help { background-image: url(../images/help.png); } +.icon-attachment { background-image: url(../images/attachment.png); } +.icon-history { background-image: url(../images/history.png); } +.icon-time { background-image: url(../images/time.png); } +.icon-time-add { background-image: url(../images/time_add.png); } +.icon-stats { background-image: url(../images/stats.png); } +.icon-warning { background-image: url(../images/warning.png); } +.icon-fav { background-image: url(../images/fav.png); } +.icon-fav-off { background-image: url(../images/fav_off.png); } +.icon-reload { background-image: url(../images/reload.png); } +.icon-lock { background-image: url(../images/locked.png); } +.icon-unlock { background-image: url(../images/unlock.png); } +.icon-checked { background-image: url(../images/true.png); } +.icon-details { background-image: url(../images/zoom_in.png); } +.icon-report { background-image: url(../images/report.png); } +.icon-comment { background-image: url(../images/comment.png); } +.icon-summary { background-image: url(../images/lightning.png); } +.icon-server-authentication { background-image: url(../images/server_key.png); } +.icon-issue { background-image: url(../images/ticket.png); } +.icon-zoom-in { background-image: url(../images/zoom_in.png); } +.icon-zoom-out { background-image: url(../images/zoom_out.png); } + +.icon-file { background-image: url(../images/files/default.png); } +.icon-file.text-plain { background-image: url(../images/files/text.png); } +.icon-file.text-x-c { background-image: url(../images/files/c.png); } +.icon-file.text-x-csharp { background-image: url(../images/files/csharp.png); } +.icon-file.text-x-php { background-image: url(../images/files/php.png); } +.icon-file.text-x-ruby { background-image: url(../images/files/ruby.png); } +.icon-file.text-xml { background-image: url(../images/files/xml.png); } +.icon-file.image-gif { background-image: url(../images/files/image.png); } +.icon-file.image-jpeg { background-image: url(../images/files/image.png); } +.icon-file.image-png { background-image: url(../images/files/image.png); } +.icon-file.image-tiff { background-image: url(../images/files/image.png); } +.icon-file.application-pdf { background-image: url(../images/files/pdf.png); } +.icon-file.application-zip { background-image: url(../images/files/zip.png); } +.icon-file.application-x-gzip { background-image: url(../images/files/zip.png); } + +img.gravatar { + padding: 2px; + border: solid 1px #d5d5d5; + background: #fff; +} + +div.issue img.gravatar { + float: right; + margin: 0 0 0 1em; + padding: 5px; +} + +div.issue table img.gravatar { + height: 14px; + width: 14px; + padding: 2px; + float: left; + margin: 0 0.5em 0 0; +} + +h2 img.gravatar { + padding: 3px; + margin: -2px 4px -4px 0; + vertical-align: top; +} + +h4 img.gravatar { + padding: 3px; + margin: -6px 0 -4px 0; + vertical-align: top; +} + +td.username img.gravatar { + margin: 0 0.5em 0 0; + vertical-align: top; +} + +#activity dt img.gravatar { + float: left; + margin: 0 1em 1em 0; +} + +/* Used on 12px Gravatar img tags without the icon background */ +.icon-gravatar { + float: left; + margin-right: 4px; +} + +#activity dt, +.journal { + clear: left; +} + +.journal-link { + float: right; +} + +h2 img { vertical-align:middle; } + +.hascontextmenu { cursor: context-menu; } + +/***** Media print specific styles *****/ +@media print { + #top-menu, #header, #main-menu, #sidebar, #footer, .contextual, .other-formats { display:none; } + #main { background: #fff; } + #content { width: 99%; margin: 0; padding: 0; border: 0; background: #fff; overflow: visible !important;} + #wiki_add_attachment { display:none; } + .hide-when-print { display: none; } +}
--- a/public/stylesheets/application.css Mon Jun 06 14:24:13 2011 +0100 +++ b/public/stylesheets/application.css Mon Jun 06 14:41:04 2011 +0100 @@ -27,7 +27,9 @@ #header {height:5.3em;margin:0;background-color:#507AAA;color:#f8f8f8; padding: 4px 8px 0px 6px; position:relative;} #header a {color:#f8f8f8;} #header h1 a.ancestor { font-size: 80%; } -#quick-search {float:right;} + +#project-search-jump {float:right; } + #main-menu {position: absolute; bottom: 0px; left:6px; margin-right: -500px;} #main-menu ul {margin: 0; padding: 0;} @@ -361,8 +363,7 @@ ul.projects ul.projects { border-left: 3px solid #e0e0e0; } ul.projects li.root { list-style-type:none; margin-bottom: 1em; } ul.projects li.child { list-style-type:none; margin-top: 1em;} -ul.projects div.root a.project { font-family: "Trebuchet MS", Verdana, sans-serif; font-weight: bold; font-size: 16px; margin: 0 0 10px 0; } -.my-project { padding-left: 18px; background: url(../images/fav.png) no-repeat 0 50%; } +ul.projects div.root a.project { font-weight: bold; font-size: 16px; margin: 0 0 10px 0; } #tracker_project_ids ul { margin: 0; padding-left: 1em; } #tracker_project_ids li { list-style-type:none; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/public/themes/soundsoftware/stylesheets/application.css Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,205 @@ +@import url(../../../stylesheets/application.css); +@import url(fonts.css); + +/* Colours: + + #be5700 link (orange) + + #3e442c text (dark green) + (OK for headings, but small text is easier to read in black) + + #ffa801 logo (yellow) + + #525a38 logotype (olive) + + #fdfaf0 background (cream) + + #fdfbf5 alternate background (lighter cream) + + #ffe69b highlight (light yellow) + + #a9b680 detail (light green) +*/ + +body { + background: #fdfbf5; + color: #000; + margin: 0; + margin-bottom: 40px; + min-width: 620px; +} + +h1 { + color: #3e442c; + font-family: GilliusADFNo2, 'Gill Sans', Tahoma, sans-serif; + font-weight: normal; +} + +body,p,h2,h3,h4,li,table,.wiki h1 { + font-family: DroidSans, 'Liberation Sans', tahoma, verdana, sans-serif; +} + +h2,h3,h4,.wiki h1 { + color: #3e442c; +} + +h2,.wiki h1 { + font-size: 1.8em; +} + +.box { + padding: 6px; + margin-bottom: 10px; + background-color: #fdfaf0; + color: #3e442c; + line-height: 1.5em; + border: 1px solid #a9b680; + border-left: 4px solid #a9b680; +} + +.odd {background-color:#fdf7e4;} +.even {background-color: #fdfaf0;} + +#content .tabs { margin-bottom: 0; } + +table.list th { background-color: #fdfaf0; border-bottom: 1px solid #a9b680; } +table.list { border: 1px solid #a9b680; /* border-left: 4px solid #a9b680; */ } +tr.entry { border-left: 1px solid #a9b680; border-right: 1px solid #a9b680; } +tr.entry:last-child { border-bottom: 1px solid #a9b680; } + +table.projects th { text-align: left; } +table.projects th.managers { color: #3e442c; } +table.projects .root .name { font-size: 1.2em; padding-top: 0.3em; } +table.projects .description { padding-bottom: 0.5em; } +table.projects .no_description { padding-bottom: 0.5em; } +table.projects .hosted_here { font-weight: bold; } +table.projects .child .name { font-weight: normal; } +table.projects .child .description { font-size: 0.95em; } +table.projects .child .firstcol { padding-left: 1em } +table.projects .level2 .firstcol { padding-left: 2em; } +table.projects .level3 .firstcol { padding-left: 3em; } + +ul.projects .public, ul.projects .private { padding-left: 0.5em; color: #3e442c; font-size: 0.95em } + +#top-menu { position: absolute; top: 0; z-index: 1; left: 0px; width: 100%; font-size: 90%; /* height: 2em; */ margin: 0; padding: 0; padding-top: 0.5em; background-color: #3e442c; } +#top-menu ul { margin-left: 10px; } +#top-menu a { font-weight: bold; } +#header { position: absolute; z-index: 0; top: 0; width: 100%; background: #fdfbf5; border-bottom: 2px solid #a9b680; /* height:80px; */ padding: 20px 0 0.5em 0; margin-bottom: 0; } +#header a { color: #be5700; } +#header h1 { color: #525a38; margin-top: 25px; font-size: 3em; font-weight: normal; margin-left: 10px; } +.header-general h1 { + background: url('soundsoftware-logo-title-only-transparent-beta.png') no-repeat 0 0; + text-indent: -9999px; + width: 500px; + height: 34px; + } + +#quick-search { margin-right: 6px; margin-top: 1em; color: #000; } +#project-jump-box { float: right; margin-right: 6px; margin-top: 5px; color: #000; } +#project-ancestors-title { + margin-bottom: 0px; + margin-left: 10px; + margin-top: 6px; + font-family: GilliusADFNo2, 'Gill Sans', Tahoma, sans-serif; + font-weight: normal; +} + +#main-menu { position: absolute; top: 100px; /* background-color: #be5700; */ left: 0; border-top: 0; width: 100%;/* height: 1.82em; */ padding: 0; margin: 0; border: 0; } +#main-menu li { margin: 0; padding: 0; } +#main-menu li a { background-color: #fdfbf5; color: #be5700; border-right: 1px solid #a9b680; font-size: 97%; padding: 0em 8px 0.2em 10px; font-weight: normal; } +#main-menu li:last-child a { border-right: 0; } +#main-menu li a:hover { background-color: #fdfbf5; color: #be5700; text-decoration: underline; } +#main-menu li a.selected, #main-menu li a.selected:hover { background-color: #fdfbf5; color: #3e442c; } + +#footer { background-color: #fdfbf5; border: 0; border-top: 2px solid #a9b680; color: #3e442c; text-align: right; } +#footer a { color: #be5700; font-weight: bold; } + +#main { margin-top: 135px; font:95%; background: #fdfaf0; } +#main a { font-weight: medium; color: #be5700;} +#main a:hover { color: #be5700; text-decoration: underline; } +#content { background: #fdfbf5; } +/*#content .tabs ul { bottom:-1px; } +*/ +h2, h3, h4, .wiki h1, .wiki h2, .wiki h3 { border-bottom: 0px; } +/*h2, .wiki h1 { letter-spacing:-1px; } +*/ +h4 { border-bottom: dotted 1px #c0c0c0; } + +div.issue { background: #fdfaf0; border: 1px solid #a9b680; border-left: 4px solid #a9b680; } + +#top-menu a.home, #top-menu a.my-page, #top-menu a.projects, #top-menu a.administration, #top-menu a.help { + background-position: 0% 40%; + background-repeat: no-repeat; + padding-left: 20px; + padding-top: 2px; + padding-bottom: 3px; +} + +#top-menu a.home { background-image: url(../images/home.png); } +#top-menu a.my-page { background-image: url(../../../images/user.png); } +#top-menu a.projects { background-image: url(../../../images/projects.png); } +#top-menu a.administration { background-image: url(../images/wrench.png); } +#top-menu a.help { background-image: url(../../../images/help.png); } + +/* for Javadoc in Embedded context: */ + +.TableHeadingColor { background-color: #fdf7e4; color: #3e442c; border: 0px solid #fff; } +.TableHeadingColor th { background-color: #fdf7e4; color: #3e442c; border: 1px solid #a9b680; } +.TableHeadingColor th font { font-size: 1.4em; color: #3e442c; } +.TableSubHeadingColor { background-color: #fdfaf0; color: #3e442c; border: 0px solid #fff; } +.TableSubHeadingColor th { background-color: #fdfaf0; color: #3e442c; border: 1px solid #a9b680; } +.TableRowColor { background-color: #fdfbf5; color: #000000; border: 0; } +.TableRowColor td { background-color: #fdfbf5; color: #000000; border: 0; } +.NavBarCell1 { background-color: #ffe69b; color:#000000 } + +.embedded table { border: 0px solid #fff; } +.embedded h1 { font-family: DroidSans, 'Liberation Sans', tahoma, verdana, sans-serif; } +.embedded h3 { margin-top: 0.5em; } +.embedded hr { color: #a9b680; background-color: #a9b680 } +.embedded center { text-align: left; } /* haha */ + +/* Special hack to hide the FRAMES | NO FRAMES links -- they don't + work in this context -- and right-align the All Classes and Detail links */ +.embedded .NavBarCell2 a[target=_top] { width: 0px; visibility: hidden; } +.embedded .NavBarCell2 + .NavBarCell2 { text-align: right; } +.embedded .NavBarCell3 + .NavBarCell3 { text-align: right; } + +/* For Doxygen in Embedded context (though note some of the Javadoc + rules will also apply to Doxygen): */ + +.memItemLeft, +.memItemRight, +.memTemplParams, +.memTemplItemLeft, +.memTemplItemRight, +.indexkey, +.indexvalue, +.memproto, +.memproto td, +.memdoc a, +.embedded li .el, +.embedded a.el { font-family: monospace; } + +.embedded .memTemplParams { font-style: italic; } + +.embedded .memItemRight a:first-child, +.embedded .memTemplItemRight a:first-child, +.embedded .indexkey a:first-child, +.embedded a.el, +.embedded .memdoc a { font-weight: bold; } /* function names, etc */ + +.embedded .memitem { border-bottom: 1px solid #a9b680; padding-top: 0.5em; } +.embedded .memitem:last-child { border-bottom: 0px; } + +.embedded .contents { margin-top: 0.5em; } +.embedded .contents td { padding: 0px; } + +.embedded .contents h1, +.embedded .contents h2, +.embedded .navigation h1, +.embedded .navigation h2 { padding-top: 0.5em; padding-bottom: 0.25em; } + +.embedded .contents .center { text-align: center; } /* undo javadoc hack above */ + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/public/themes/soundsoftware/stylesheets/fonts.css Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,83 @@ + +/* Font pack generated by FontSquirrel */ + +@font-face { + font-family: 'GilliusADFNo2'; + src: url('fonts/gilliusadfno2-bolditalic-webfont.eot'); + src: local('☺'), url('fonts/gilliusadfno2-bolditalic-webfont.woff') format('woff'), url('fonts/gilliusadfno2-bolditalic-webfont.ttf') format('truetype'), url('fonts/GilliusADFNo2-BoldItalic.otf') format('opentype'), url('fonts/gilliusadfno2-bolditalic-webfont.svg#webfontLmhvPwzc') format('svg'); + font-weight: bold; + font-style: italic; +} + +@font-face { + font-family: 'GilliusADFNo2'; + src: url('fonts/gilliusadfno2-italic-webfont.eot'); + src: local('☺'), url('fonts/gilliusadfno2-italic-webfont.woff') format('woff'), url('fonts/gilliusadfno2-italic-webfont.ttf') format('truetype'), url('fonts/GilliusADFNo2-Italic.otf') format('opentype'), url('fonts/gilliusadfno2-italic-webfont.svg#webfonteHBtzgS0') format('svg'); + font-weight: normal; + font-style: italic; +} + +@font-face { + font-family: 'GilliusADFNo2'; + src: url('fonts/gilliusadfno2-bold-webfont.eot'); + src: local('☺'), url('fonts/gilliusadfno2-bold-webfont.woff') format('woff'), url('fonts/gilliusadfno2-bold-webfont.ttf') format('truetype'), url('fonts/GilliusADFNo2-Bold.otf') format('opentype'), url('fonts/gilliusadfno2-bold-webfont.svg#webfontntXmQMqk') format('svg'); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: 'GilliusADFNo2'; + src: url('fonts/gilliusadfno2-regular-webfont.eot'); + src: local('☺'), url('fonts/gilliusadfno2-regular-webfont.woff') format('woff'), url('fonts/gilliusadfno2-regular-webfont.ttf') format('truetype'), url('fonts/GilliusADFNo2-Regular.otf') format('opentype'), url('fonts/gilliusadfno2-regular-webfont.svg#webfontvJUiAdi3') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'LiberationSans'; + src: url('fonts/liberationsans-italic-webfont.eot'); + src: local('☺'), url('fonts/liberationsans-italic-webfont.woff') format('woff'), url('fonts/liberationsans-italic-webfont.ttf') format('truetype'), url('fonts/liberationsans-italic-webfont.svg#webfontBdDf5JP3') format('svg'); + font-weight: normal; + font-style: italic; +} + +@font-face { + font-family: 'LiberationSans'; + src: url('fonts/liberationsans-bolditalic-webfont.eot'); + src: local('☺'), url('fonts/liberationsans-bolditalic-webfont.woff') format('woff'), url('fonts/liberationsans-bolditalic-webfont.ttf') format('truetype'), url('fonts/liberationsans-bolditalic-webfont.svg#webfontTNmZRY7v') format('svg'); + font-weight: bold; + font-style: italic; +} + +@font-face { + font-family: 'LiberationSans'; + src: url('fonts/liberationsans-bold-webfont.eot'); + src: local('☺'), url('fonts/liberationsans-bold-webfont.woff') format('woff'), url('fonts/liberationsans-bold-webfont.ttf') format('truetype'), url('fonts/liberationsans-bold-webfont.svg#webfontslkXRzon') format('svg'); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: 'LiberationSans'; + src: url('fonts/liberationsans-regular-webfont.eot'); + src: local('☺'), url('fonts/liberationsans-regular-webfont.woff') format('woff'), url('fonts/liberationsans-regular-webfont.ttf') format('truetype'), url('fonts/liberationsans-regular-webfont.svg#webfontV0O783dY') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'DroidSans'; + src: url('fonts/DroidSans-webfont.eot'); + src: local('☺'), url('fonts/DroidSans-webfont.woff') format('woff'), url('fonts/DroidSans-webfont.ttf') format('truetype'), url('fonts/DroidSans-webfont.svg#webfontKYIQSBQk') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'DroidSans'; + src: url('fonts/DroidSans-Bold-webfont.eot'); + src: local('☺'), url('fonts/DroidSans-Bold-webfont.woff') format('woff'), url('fonts/DroidSans-Bold-webfont.ttf') format('truetype'), url('fonts/DroidSans-Bold-webfont.svg#webfontljpTCDjw') format('svg'); + font-weight: bold; + font-style: normal; +} +
Binary file public/themes/soundsoftware/stylesheets/soundsoftware-logo-title-only-transparent-beta.png has changed
Binary file public/themes/soundsoftware/stylesheets/soundsoftware-logo-title-only-transparent-beta.xcf has changed
Binary file public/themes/soundsoftware/stylesheets/soundsoftware-logo-title-only-transparent.png has changed
--- a/public/themes/ssamr/stylesheets/application.css Mon Jun 06 14:24:13 2011 +0100 +++ b/public/themes/ssamr/stylesheets/application.css Mon Jun 06 14:41:04 2011 +0100 @@ -20,6 +20,19 @@ src: url('DroidSans-Bold.ttf'); } +@font-face +{ + font-family: Gillius; + src: url('GilliusADFNo2-Regular.otf'); +} + +@font-face +{ + font-family: Gillius; + font-weight: bold; + src: url('GilliusADFNo2-Bold.otf'); +} + body { background: #ffffff; color: #404040;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/fixtures/institutions.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,7 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +one: + name: MyString + +two: + name: MyString
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/fixtures/mail_handler/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,131 @@ +K 25 +svn:wc:ra_dav:version-url +V 51 +/svn/!svn/ver/4575/trunk/test/fixtures/mail_handler +END +ticket_html_only.eml +K 25 +svn:wc:ra_dav:version-url +V 72 +/svn/!svn/ver/2136/trunk/test/fixtures/mail_handler/ticket_html_only.eml +END +message_reply_by_subject.eml +K 25 +svn:wc:ra_dav:version-url +V 80 +/svn/!svn/ver/2294/trunk/test/fixtures/mail_handler/message_reply_by_subject.eml +END +issue_update_with_multiple_quoted_reply_above.eml +K 25 +svn:wc:ra_dav:version-url +V 101 +/svn/!svn/ver/4361/trunk/test/fixtures/mail_handler/issue_update_with_multiple_quoted_reply_above.eml +END +ticket_with_localized_attributes.eml +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/!svn/ver/4395/trunk/test/fixtures/mail_handler/ticket_with_localized_attributes.eml +END +ticket_with_spaces_between_attribute_and_separator.eml +K 25 +svn:wc:ra_dav:version-url +V 106 +/svn/!svn/ver/2838/trunk/test/fixtures/mail_handler/ticket_with_spaces_between_attribute_and_separator.eml +END +ticket_with_long_subject.eml +K 25 +svn:wc:ra_dav:version-url +V 80 +/svn/!svn/ver/3801/trunk/test/fixtures/mail_handler/ticket_with_long_subject.eml +END +ticket_from_emission_address.eml +K 25 +svn:wc:ra_dav:version-url +V 84 +/svn/!svn/ver/3022/trunk/test/fixtures/mail_handler/ticket_from_emission_address.eml +END +ticket_with_cc.eml +K 25 +svn:wc:ra_dav:version-url +V 70 +/svn/!svn/ver/2077/trunk/test/fixtures/mail_handler/ticket_with_cc.eml +END +ticket_with_attributes.eml +K 25 +svn:wc:ra_dav:version-url +V 78 +/svn/!svn/ver/1643/trunk/test/fixtures/mail_handler/ticket_with_attributes.eml +END +japanese_keywords_iso_2022_jp.eml +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/!svn/ver/3322/trunk/test/fixtures/mail_handler/japanese_keywords_iso_2022_jp.eml +END +ticket_with_attachment.eml +K 25 +svn:wc:ra_dav:version-url +V 78 +/svn/!svn/ver/1568/trunk/test/fixtures/mail_handler/ticket_with_attachment.eml +END +ticket_by_empty_user.eml +K 25 +svn:wc:ra_dav:version-url +V 76 +/svn/!svn/ver/3783/trunk/test/fixtures/mail_handler/ticket_by_empty_user.eml +END +ticket_by_unknown_user.eml +K 25 +svn:wc:ra_dav:version-url +V 78 +/svn/!svn/ver/2789/trunk/test/fixtures/mail_handler/ticket_by_unknown_user.eml +END +ticket_with_invalid_attributes.eml +K 25 +svn:wc:ra_dav:version-url +V 86 +/svn/!svn/ver/4404/trunk/test/fixtures/mail_handler/ticket_with_invalid_attributes.eml +END +ticket_reply_with_status.eml +K 25 +svn:wc:ra_dav:version-url +V 80 +/svn/!svn/ver/4575/trunk/test/fixtures/mail_handler/ticket_reply_with_status.eml +END +ticket_on_given_project.eml +K 25 +svn:wc:ra_dav:version-url +V 79 +/svn/!svn/ver/4394/trunk/test/fixtures/mail_handler/ticket_on_given_project.eml +END +issue_update_with_quoted_reply_above.eml +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/!svn/ver/4361/trunk/test/fixtures/mail_handler/issue_update_with_quoted_reply_above.eml +END +ticket_with_custom_fields.eml +K 25 +svn:wc:ra_dav:version-url +V 81 +/svn/!svn/ver/2211/trunk/test/fixtures/mail_handler/ticket_with_custom_fields.eml +END +ticket_reply.eml +K 25 +svn:wc:ra_dav:version-url +V 68 +/svn/!svn/ver/2288/trunk/test/fixtures/mail_handler/ticket_reply.eml +END +message_reply.eml +K 25 +svn:wc:ra_dav:version-url +V 69 +/svn/!svn/ver/2289/trunk/test/fixtures/mail_handler/message_reply.eml +END +ticket_without_from_header.eml +K 25 +svn:wc:ra_dav:version-url +V 82 +/svn/!svn/ver/2553/trunk/test/fixtures/mail_handler/ticket_without_from_header.eml +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/fixtures/ssamr_user_details.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,7 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +# one: +# column: value +# +# two: +# column: value
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/integration/lib/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 45 +/svn/!svn/ver/4560/trunk/test/integration/lib +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/integration/lib/redmine/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/4560/trunk/test/integration/lib/redmine +END +menu_manager_test.rb +K 25 +svn:wc:ra_dav:version-url +V 74 +/svn/!svn/ver/4509/trunk/test/integration/lib/redmine/menu_manager_test.rb +END +themes_test.rb +K 25 +svn:wc:ra_dav:version-url +V 68 +/svn/!svn/ver/4560/trunk/test/integration/lib/redmine/themes_test.rb +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/unit/institution_test.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,8 @@ +require 'test_helper' + +class InstitutionTest < ActiveSupport::TestCase + # Replace this with your real tests. + test "the truth" do + assert true + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/unit/lib/redmine/helpers/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/4582/trunk/test/unit/lib/redmine/helpers +END +gantt_test.rb +K 25 +svn:wc:ra_dav:version-url +V 68 +/svn/!svn/ver/4582/trunk/test/unit/lib/redmine/helpers/gantt_test.rb +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/unit/lib/redmine/menu_manager/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,23 @@ +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/4509/trunk/test/unit/lib/redmine/menu_manager +END +menu_item_test.rb +K 25 +svn:wc:ra_dav:version-url +V 77 +/svn/!svn/ver/4509/trunk/test/unit/lib/redmine/menu_manager/menu_item_test.rb +END +menu_helper_test.rb +K 25 +svn:wc:ra_dav:version-url +V 79 +/svn/!svn/ver/4509/trunk/test/unit/lib/redmine/menu_manager/menu_helper_test.rb +END +mapper_test.rb +K 25 +svn:wc:ra_dav:version-url +V 74 +/svn/!svn/ver/4509/trunk/test/unit/lib/redmine/menu_manager/mapper_test.rb +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/unit/lib/redmine/scm/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 50 +/svn/!svn/ver/4964/trunk/test/unit/lib/redmine/scm +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/unit/lib/redmine/scm/adapters/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,47 @@ +K 25 +svn:wc:ra_dav:version-url +V 59 +/svn/!svn/ver/4964/trunk/test/unit/lib/redmine/scm/adapters +END +subversion_adapter_test.rb +K 25 +svn:wc:ra_dav:version-url +V 86 +/svn/!svn/ver/4825/trunk/test/unit/lib/redmine/scm/adapters/subversion_adapter_test.rb +END +bazaar_adapter_test.rb +K 25 +svn:wc:ra_dav:version-url +V 82 +/svn/!svn/ver/4836/trunk/test/unit/lib/redmine/scm/adapters/bazaar_adapter_test.rb +END +git_adapter_test.rb +K 25 +svn:wc:ra_dav:version-url +V 79 +/svn/!svn/ver/4964/trunk/test/unit/lib/redmine/scm/adapters/git_adapter_test.rb +END +mercurial_adapter_test.rb +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/!svn/ver/4875/trunk/test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb +END +filesystem_adapter_test.rb +K 25 +svn:wc:ra_dav:version-url +V 86 +/svn/!svn/ver/4509/trunk/test/unit/lib/redmine/scm/adapters/filesystem_adapter_test.rb +END +cvs_adapter_test.rb +K 25 +svn:wc:ra_dav:version-url +V 79 +/svn/!svn/ver/4832/trunk/test/unit/lib/redmine/scm/adapters/cvs_adapter_test.rb +END +darcs_adapter_test.rb +K 25 +svn:wc:ra_dav:version-url +V 81 +/svn/!svn/ver/4748/trunk/test/unit/lib/redmine/scm/adapters/darcs_adapter_test.rb +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/unit/lib/redmine/views/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 52 +/svn/!svn/ver/4509/trunk/test/unit/lib/redmine/views +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/unit/lib/redmine/views/builders/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 61 +/svn/!svn/ver/4509/trunk/test/unit/lib/redmine/views/builders +END +xml_test.rb +K 25 +svn:wc:ra_dav:version-url +V 73 +/svn/!svn/ver/4509/trunk/test/unit/lib/redmine/views/builders/xml_test.rb +END +json_test.rb +K 25 +svn:wc:ra_dav:version-url +V 74 +/svn/!svn/ver/4509/trunk/test/unit/lib/redmine/views/builders/json_test.rb +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/unit/ssamr_user_details_test.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,8 @@ +require 'test_helper' + +class SsamrUserDetailsTest < ActiveSupport::TestCase + # Replace this with your real tests. + test "User Id should be correct" do + assert_equal user_id, user.id + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unis.txt Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,141 @@ +University of Aberdeen +University of Abertay Dundee +Aberystwyth University +Anglia Ruskin University +University of the Arts London +Aston University +Bangor University +University of Bath +Bath Spa University +University of Bedfordshire +Birkbeck, University of London +University of Birmingham +Birmingham City University +Birmingham Conservatoire +University Centre at Blackburn College +University of Bolton +Bournemouth University +University of Bradford +University of Brighton +University of Bristol +Brunel University +University of Buckingham +Buckinghamshire New University +University of Cambridge +Institute of Cancer Research, University of London +Canterbury Christ Church University +Cardiff University +University of Central Lancashire +Central School of Speech and Drama, University of London +University of Chester +University of Chichester +City University London +Courtauld Institute of Art +Coventry University +Cranfield University +University for the Creative Arts +University of Cumbria +De Montfort University +University of Derby +University of Dundee +Durham University +University of East Anglia +University of East London +Edge Hill University +University of Edinburgh +Edinburgh Napier University +Institute of Education, University of London +University of Essex +University of Exeter +University of Glamorgan +University of Glasgow +Glasgow Caledonian University +University of Gloucestershire +Goldsmiths, University of London +University of Greenwich +Glyndŵr University +Heriot-Watt University +University of Hertfordshire +Heythrop College +University of Huddersfield +University of Hull +Hull York Medical School +Imperial College London +Keele University +University of Kent +King's College London +Kingston University +Lancaster University +University of Leeds +Leeds Metropolitan University +University of Leicester +University of Lincoln +University of Liverpool +Liverpool Hope University +Liverpool John Moores University +London Business School +London College of Music +London Metropolitan University +London School of Economics and Political Science +London School of Hygiene and Tropical Medicine +London South Bank University +Loughborough University +University of Manchester +Manchester Metropolitan University +Middlesex University +Newcastle University +University of Northampton +Northumbria University +University of Nottingham +Nottingham Trent University +The Open University +University of Oxford +Oxford Brookes University +Peninsula College of Medicine and Dentistry +University of Plymouth +University of Portsmouth +Queen's University Belfast +Queen Margaret University +Queen Mary, University of London +University of Reading +The Robert Gordon University, Aberdeen +Roehampton University +Royal Academy of Music +Royal College of Art +Royal Holloway, University of London +Royal Veterinary College +University of St Andrews +St George's, University of London +University of Salford +School of Advanced Study, University of London +School of Oriental and African Studies +School of Pharmacy, University of London +University of Sheffield +Sheffield Hallam University +University of Southampton +Southampton Solent University +Staffordshire University +University of Stirling +University of Strathclyde +University of Sunderland +University of Surrey +University of Sussex +Swansea Metropolitan University +Swansea University +University of Teesside +Thames Valley University +University of Ulster +University College London +University of Wales +University of Wales Institute, Cardiff +University of Wales, Newport +University of Wales, Trinity Saint David +University of Warwick +University of Westminster +University of the West of England +University of the West of Scotland +University of Winchester +University of Wolverhampton +University of Worcester +University of York +York St John University
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unis.txt.~1~ Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,245 @@ +University of Aberdeen +University of Abertay Dundee +Aberystwyth University +Anglia Ruskin University +University of the Arts London + +Camberwell College of Arts +Central Saint Martins College of Art and Design +Chelsea College of Art and Design +London College of Communication +London College of Fashion +Wimbledon College of Art + + +Aston University +Bangor University +University of Bath +Bath Spa University +University of Bedfordshire +University of Ulster +University of Birmingham +Birmingham City University + +Birmingham Conservatoire + + +Blackburn +University of Bolton +Bournemouth University +University of Bradford + +University of Bradford School of Management + + +University of Brighton +University of Sussex +University of Bristol +Brunel University +University of Buckingham +Buckinghamshire New University +University of Cambridge +Canterbury Christ Church University +Cardiff University + +Cardiff International Academy of Voice +Cardiff University School of Medicine + + +Preston +Warrington +University of Chichester +The Open University +City University London + +Cass Business School +City Law School + + +Coventry University +Cranfield University +University for the Creative Arts +University of Cumbria +De Montfort University +University of Derby +University of Dundee +Thornaby-on-Tees (Queen's Campus) +University of East Anglia +University of East London +Edge Hill University +University of Edinburgh + +Moray House School of Education + + +Edinburgh Napier University +University of Essex +University of Exeter + +Camborne School of Mines + + +University of Glamorgan +University of Glasgow +Glasgow Caledonian University +University of Gloucestershire +University of Greenwich +GlyndE5r University +Heriot-Watt University +University of Hertfordshire +University of Huddersfield +University of Hull +Hull York Medical School +Imperial College London + +Imperial College at Wye +Royal School of Mines + + +Keele University +University of Kent +Kingston University +Lancaster University +University of Leeds + +Leeds Trinity & All Saints + + +Leeds Metropolitan University +University of Leicester +University of Lincoln +University of Liverpool + +Liverpool School of Tropical Medicine + + +Liverpool Hope University +Liverpool John Moores University +University of London + +Birkbeck, University of London +Central School of Speech and Drama +Courtauld Institute of Art +Goldsmiths, University of London +Heythrop College +Institute of Cancer Research +Institute of Education +King's College London + +Institute of Psychiatry + + +London Business School +London School of Economics and Political Science +London School of Hygiene and Tropical Medicine +Queen Mary, University of London +Royal Academy of Music +Royal Holloway, University of London +Royal Veterinary College +St George's, University of London +School of Advanced Study + +Institute for the Study of the Americas +Institute of Advanced Legal Studies +Institute of Classical Studies +Institute of Commonwealth Studies +Institute of English Studies +Institute of Germanic & Romance Studies +Institute of Historical Research +Institute of Musical Research +Institute of Philosophy +Warburg Institute + + +School of Oriental and African Studies +School of Pharmacy, University of London +University College London + +Eastman Dental Institute +Institute of Archaeology +Institute of Child Health +Institute of Neurology +School of Slavonic and East European Studies + + +University of Glasgow + + +London Metropolitan University +London South Bank University +Loughborough University +University of Manchester + +Manchester Business School + + +Manchester Metropolitan University +Middlesex University +Newcastle University +University of Northampton +Northumbria University +University of Nottingham +Nottingham Trent University +The Open University + +Royal College of Nursing Institute + + +University of Oxford +Oxford Brookes University +Peninsula College of Medicine and Dentistry +University of Plymouth +University of Portsmouth +Queen's University Belfast + +Belfast Bible College + + +Queen Margaret University +University of Reading + +Henley Business School + + +The Robert Gordon University +Roehampton University +Royal College of Art +University of St Andrews +University of Salford +University of Sheffield +Sheffield Hallam University +University of Southampton +Southampton Solent University +Staffordshire University +University of Stirling +University of Strathclyde +University of Sunderland +University of Surrey +University of Sussex +Swansea Metropolitan University +Swansea University +University of Teesside +Thames Valley University + +London College of Music + + +University of Ulster +University of Wales +University of Wales Institute, Cardiff +University of Wales, Newport +University of Wales, Trinity Saint David +University of Warwick +University of Westminster +University of the West of England +University of the West of Scotland +University of Winchester +University of Wolverhampton +University of Worcester + +Worcester Business School + + +University of York +York St John University +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unis.txt.~2~ Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,141 @@ +University of Aberdeen +University of Abertay Dundee +Aberystwyth University +Anglia Ruskin University +University of the Arts London +Aston University +Bangor University +University of Bath +Bath Spa University +University of Bedfordshire +Birkbeck, University of London +University of Birmingham +Birmingham City University +Birmingham Conservatoire +University Centre at Blackburn College +University of Bolton +Bournemouth University +University of Bradford +University of Brighton +University of Bristol +Brunel University +University of Buckingham +Buckinghamshire New University +University of Cambridge +Institute of Cancer Research, University of London +Canterbury Christ Church University +Cardiff University +University of Central Lancashire +Central School of Speech and Drama, University of London +University of Chester +University of Chichester +City University London +Courtauld Institute of Art +Coventry University +Cranfield University +University for the Creative Arts +University of Cumbria +De Montfort University +University of Derby +University of Dundee +Durham University +University of East Anglia +University of East London +Edge Hill University +University of Edinburgh +Edinburgh Napier University +Institute of Education, University of London +University of Essex +University of Exeter +University of Glamorgan +University of Glasgow +Glasgow Caledonian University +University of Gloucestershire +Goldsmiths, University of London +University of Greenwich +Glyndŵr University +Heriot-Watt University +University of Hertfordshire +Heythrop College +University of Huddersfield +University of Hull +Hull York Medical School +Imperial College London +Keele University +University of Kent +King's College London +Kingston University +Lancaster University +University of Leeds +Leeds Metropolitan University +University of Leicester +University of Lincoln +University of Liverpool +Liverpool Hope University +Liverpool John Moores University +London Business School +London College of Music +London Metropolitan University +London School of Economics and Political Science +London School of Hygiene and Tropical Medicine +London South Bank University +Loughborough University +University of Manchester +Manchester Metropolitan University +Middlesex University +Newcastle University +University of Northampton +Northumbria University +University of Nottingham +Nottingham Trent University +The Open University +University of Oxford +Oxford Brookes University +Peninsula College of Medicine and Dentistry +University of Plymouth +University of Portsmouth +Queen's University Belfast +Queen Margaret University +Queen Mary, University of London +University of Reading +The Robert Gordon University, Aberdeen +Roehampton University +Royal Academy of Music +Royal College of Art +Royal Holloway, University of London +Royal Veterinary College +University of St Andrews +St George's, University of London +University of Salford +School of Advanced Study, University of London +School of Oriental and African Studies +School of Pharmacy, University of London +University of Sheffield +Sheffield Hallam University +University of Southampton +Southampton Solent University +Staffordshire University +University of Stirling +University of Strathclyde +University of Sunderland +University of Surrey +University of Sussex +Swansea Metropolitan University +Swansea University +University of Teesside +Thames Valley University +University of Ulster +University College London +University of Wales +University of Wales Institute, Cardiff +University of Wales, Newport +University of Wales, Trinity Saint David +University of Warwick +University of Westminster +University of the West of England +University of the West of Scotland +University of Winchester +University of Wolverhampton +University of Worcester +University of York +York St John University
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/acts_as_customizable/lib/.svn/all-wcprops Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 64 +/svn/!svn/ver/4891/trunk/vendor/plugins/acts_as_customizable/lib +END +acts_as_customizable.rb +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/!svn/ver/4891/trunk/vendor/plugins/acts_as_customizable/lib/acts_as_customizable.rb +END
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/COPYING Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/README Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,6 @@ +Embedded plugin for Redmine +Copyright (C) 2008 Jean-Philippe Lang + +The plugin lets you embed html pages (eg. documentation, test reports) in your projects. + +See: http://www.redmine.org/wiki/redmine/PluginEmbedded
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/RUNNING_TESTS Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,1 @@ +rake test:plugins PLUGIN=embedded
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/app/controllers/embedded_controller.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,112 @@ +# Redmine - project management software +# Copyright (C) 2008 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'iconv' + +class EmbeddedController < ApplicationController + class EmbeddedControllerError < StandardError; end + + unloadable + layout 'base' + before_filter :find_project, :authorize + + def index + path = get_real_path(params[:path]) + if File.directory?(path) + file = get_index_file(path) + target = params[:path] || [] + target << file + # Forces redirect to the index file when the requested path is a directory + # so that relative links in embedded html pages work + redirect_to :path => target + return + end + + # Check file extension + raise EmbeddedControllerError.new('This file can not be viewed (invalid extension).') unless Redmine::Plugins::Embedded.valid_extension?(path) + + if Redmine::MimeType.is_type?('image', path) + send_file path, :disposition => 'inline', :type => Redmine::MimeType.of(path) + else + embed_file path + end + + rescue Errno::ENOENT => e + # File was not found + render_404 + rescue Errno::EACCES => e + # Can not read the file + render_error "Unable to read the file: #{e.message}" + rescue EmbeddedControllerError => e + render_error e.message + end + + private + + def find_project + @project = Project.find(params[:id]) + rescue ActiveRecord::RecordNotFound + render_404 + end + + # Return the path to the html root directory for the current project + def get_project_directory + @project_directory ||= Setting.plugin_embedded['path'].to_s.gsub('{PROJECT}', @project.identifier) + end + + # Returns the absolute path of the requested file + # Parameter is an Array + def get_real_path(path) + real = get_project_directory + real = File.join(real, path) unless path.nil? || path.empty? + dir = File.expand_path(get_project_directory) + real = File.expand_path(real) + raise Errno::ENOENT unless real.starts_with?(dir) && File.exist?(real) + real + end + + # Returns the index file in the given directory + # and raises an exception if none is found + def get_index_file(dir) + indexes = Setting.plugin_embedded['index'].to_s.split + file = indexes.find {|f| File.exist?(File.join(dir, f))} + raise EmbeddedControllerError.new("No index file found in #{dir} (#{indexes.join(', ')}).") if file.nil? + file + end + + # Renders a given HTML file + def embed_file(path) + @content = File.read(path) + + # Extract html title from embedded page + if @content =~ %r{<title>([^<]*)</title>}mi + @title = $1.strip + end + + # Keep html body only + @content.gsub!(%r{^.*<body[^>]*>(.*)</body>.*$}mi, '\\1') + + # Re-encode content if needed + source_encoding = Setting.plugin_embedded['encoding'].to_s + unless source_encoding.blank? + begin; @content = Iconv.new('UTF-8', source_encoding).iconv(@content); rescue; end + end + + @doc_template = Redmine::Plugins::Embedded.detect_template_from_path(path) + render :action => 'index' + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/app/helpers/embedded_helper.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,35 @@ +# Redmine - project management software +# Copyright (C) 2008 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +module EmbeddedHelper + + # Adds include tags for assets of the given template + def asset_include_tags(template) + + Redmine::Plugins::Embedded.assets(template).each { |asset| content_for(:header_tags) { asset_include_tag(asset) } } + end + + private + + def asset_include_tag(asset) + if asset =~ %r{\.js$} + javascript_include_tag(asset, :plugin => 'embedded') + else + stylesheet_link_tag(asset, :plugin => 'embedded') + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/app/views/embedded/index.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,9 @@ +<!-- Embedded page --> +<div class="embedded"> +<%= @content %> +</div> +<!-- Embedded page end --> + +<% html_title(@title) if @title %> + +<% asset_include_tags(@doc_template) %>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/app/views/settings/_embedded.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,22 @@ +<p><label>HTML directory</label> +<%= text_field_tag 'settings[path]', @settings['path'], :size => 80 %> +<br /><em>Use {PROJECT} to include the project identifier in the path</em></p> + +<p><label>Index files</label> +<%= text_area_tag 'settings[index]', @settings['index'], :cols => 60, :rows => 3 %> +<br /><em>Space separated list of index files by priority</em></p> + +<p><label>Valid extensions</label> +<%= text_area_tag 'settings[extensions]', @settings['extensions'], :cols => 60, :rows => 3 %> +<br /><em>Space separated list of file extensions that can be viewed (case insensitive)</em></p> + +<p><label>Default template</label> +<%= select_tag 'settings[template]', options_for_select([''] + Redmine::Plugins::Embedded.available_templates, @settings['template']) %></p> + +<p><label>Files encoding</label> +<%= text_field_tag 'settings[encoding]', @settings['encoding'] %> +<br /><em>Eg. ISO-8859-1<br />Leave this field empty if HTML files are UTF-8 encoded</em></p> + +<p><label>Menu caption</label> +<%= text_field_tag 'settings[menu]', @settings['menu'], :size => 30 %> +<br /><em>Clear this field if you don't want to add a tab to the project menu</em></p>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/assets/javascripts/rcov.js Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,18 @@ +function toggleCode( id ) { + if ( document.getElementById ) + elem = document.getElementById( id ); + else if ( document.all ) + elem = eval( "document.all." + id ); + else + return false; + + elemStyle = elem.style; + + if ( elemStyle.display != "block" ) { + elemStyle.display = "block" + } else { + elemStyle.display = "none" + } + + return true; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/assets/stylesheets/doxygen.css Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,174 @@ +#content { + font-family: Geneva, Arial, Helvetica, sans-serif; +} +#content h1, h2, h3 {border: 0;} +#content h1 {margin-bottom: 1em;} +#content CAPTION { font-weight: bold } +#content DIV.qindex { + line-height: 120%; + margin-bottom: 1em; +} +#content A.qindex { + text-decoration: none; + font-weight: bold; + padding: 2px; +} +#content A.qindexHL { + text-decoration: underline; + font-weight: bold; + padding: 2px; +} +#content A.el { text-decoration: none; font-weight: bold } +#content A.elRef { font-weight: bold } +#content A.code { text-decoration: none; font-weight: normal; color: #1A419D} +#content A.codeRef { font-weight: normal; color: #1A419D} +#content DL.el { margin-left: -1cm } +#content PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +#content DIV.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + padding: 6px; +} +#content DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +#content TD.md { background-color: #F4F4FB; font-weight: bold; } +#content TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; } +#content TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; } +#content DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; + font-family: Geneva, Arial, Helvetica, sans-serif; +} +#content DIV.groupText { margin-left: 16px; font-style: italic; font-size: 14px } +#content TD.indexkey { + background-color: #eeeeff; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +#content TD.indexvalue { + background-color: #eeeeff; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +#content TR.memlist { + background-color: #f0f0f0; +} +#content P.formulaDsp { text-align: center; } +#content IMG.formulaDsp { } +#content IMG.formulaInl { vertical-align: middle; } +#content SPAN.keyword { color: #008000 } +#content SPAN.keywordtype { color: #604020 } +#content SPAN.keywordflow { color: #e08000 } +#content SPAN.comment { color: #800000 } +#content SPAN.preprocessor { color: #806020 } +#content SPAN.stringliteral { color: #002080 } +#content SPAN.charliteral { color: #008080 } +#content .mdTable { + border: 1px solid #868686; + background-color: #F4F4FB; +} +#content .mdRow { + padding: 8px 10px; +} +#content .mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 14px; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +#content .mdescRight { + padding: 0px 8px 4px 8px; + font-size: 14px; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +#content .memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-style: solid; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-family: Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; +} +#content .memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-style: solid; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-family: Geneva, Arial, Helvetica, sans-serif; + font-size: 13px; +} +#content .search { color: #003399; + font-weight: bold; +} +#content FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +#content INPUT.search { font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #eeeeff; +} +#content TD.tiny { font-size: 75%; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/assets/stylesheets/javadoc.css Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,23 @@ +/* Javadoc style sheet */ + +/* Table colors */ +.TableHeadingColor { background: #eef; } /* Dark mauve */ +.TableHeadingColor th b { font-size: 70%; } +.TableSubHeadingColor { background: #EEEEee; } /* Light mauve */ +.TableRowColor { background: #FFFFFF; } /* White */ + +/* Font used in left-hand frame lists */ +.FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif; color:#000000 } +.FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } +.FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } + +/* Navigation bar fonts and colors */ +.NavBarCell1 { background-color: inherit; } /* Light mauve */ +.NavBarCell1Rev { background-color: inherit; } /* Dark Blue */ +.NavBarFont1 { font-family: Arial, Helvetica, sans-serif;} +.NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; font-style: underline; } + +.NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000; display: none;} +.NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} + +#content table { border-collapse: collapse; border-color: #ddd; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/assets/stylesheets/rcov.css Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,525 @@ +span.cross-ref-title { + font-size: 140%; +} +span.cross-ref a { + text-decoration: none; +} +span.cross-ref { + background-color:#f3f7fa; + border: 1px dashed #333; + margin: 1em; + padding: 0.5em; + overflow: hidden; +} +a.crossref-toggle { + text-decoration: none; +} +span.marked0 { + background-color: rgb(185, 210, 200); + display: block; +} +span.marked1 { + background-color: rgb(190, 215, 205); + display: block; +} +span.inferred0 { + background-color: rgb(175, 200, 200); + display: block; +} +span.inferred1 { + background-color: rgb(180, 205, 205); + display: block; +} +span.uncovered0 { + background-color: rgb(225, 110, 110); + display: block; +} +span.uncovered1 { + background-color: rgb(235, 120, 120); + display: block; +} +span.overview { + border-bottom: 8px solid black; +} +div.overview { + border-bottom: 8px solid black; +} +#content div.footer { + font-size: 68%; + margin-top: 1.5em; +} +#content h1, h2, h3, h4, h5, h6 { + margin-bottom: 0.5em; +} +h5 { + margin-top: 0.5em; +} +.hidden { + display: none; +} +div.separator { + height: 10px; +} +/* Commented out for better readability, esp. on IE */ +/* +table tr td, table tr th { + font-size: 68%; +} +td.value table tr td { + font-size: 11px; +} +*/ +table.percent_graph { + height: 12px; + border: #808080 1px solid; + empty-cells: show; +} +table.percent_graph td.covered { + height: 10px; + background: #00f000; +} +table.percent_graph td.uncovered { + height: 10px; + background: #e00000; +} +table.percent_graph td.NA { + height: 10px; + background: #eaeaea; +} +table.report { + border-collapse: collapse; + width: 100%; +} +table.report td.heading { + background: #dcecff; + border: #d0d0d0 1px solid; + font-weight: bold; + text-align: center; +} +table.report td.heading:hover { + background: #c0ffc0; +} +table.report td.text { + border: #d0d0d0 1px solid; +} +table.report td.value, +table.report td.lines_total, +table.report td.lines_code { + text-align: right; + border: #d0d0d0 1px solid; +} +table.report tr.light { + background-color: #f6f7f8; +} +table.report tr.dark { + background-color: #fff; +} +span.run0 { + background-color: rgb(178, 204, 255); + display: block; +} +span.run1 { + background-color: rgb(178, 206, 255); + display: block; +} +span.run2 { + background-color: rgb(178, 209, 255); + display: block; +} +span.run3 { + background-color: rgb(178, 211, 255); + display: block; +} +span.run4 { + background-color: rgb(178, 214, 255); + display: block; +} +span.run5 { + background-color: rgb(178, 218, 255); + display: block; +} +span.run6 { + background-color: rgb(178, 220, 255); + display: block; +} +span.run7 { + background-color: rgb(178, 223, 255); + display: block; +} +span.run8 { + background-color: rgb(178, 225, 255); + display: block; +} +span.run9 { + background-color: rgb(178, 228, 255); + display: block; +} +span.run10 { + background-color: rgb(178, 232, 255); + display: block; +} +span.run11 { + background-color: rgb(178, 234, 255); + display: block; +} +span.run12 { + background-color: rgb(178, 237, 255); + display: block; +} +span.run13 { + background-color: rgb(178, 239, 255); + display: block; +} +span.run14 { + background-color: rgb(178, 242, 255); + display: block; +} +span.run15 { + background-color: rgb(178, 246, 255); + display: block; +} +span.run16 { + background-color: rgb(178, 248, 255); + display: block; +} +span.run17 { + background-color: rgb(178, 251, 255); + display: block; +} +span.run18 { + background-color: rgb(178, 253, 255); + display: block; +} +span.run19 { + background-color: rgb(178, 255, 253); + display: block; +} +span.run20 { + background-color: rgb(178, 255, 249); + display: block; +} +span.run21 { + background-color: rgb(178, 255, 247); + display: block; +} +span.run22 { + background-color: rgb(178, 255, 244); + display: block; +} +span.run23 { + background-color: rgb(178, 255, 242); + display: block; +} +span.run24 { + background-color: rgb(178, 255, 239); + display: block; +} +span.run25 { + background-color: rgb(178, 255, 235); + display: block; +} +span.run26 { + background-color: rgb(178, 255, 233); + display: block; +} +span.run27 { + background-color: rgb(178, 255, 230); + display: block; +} +span.run28 { + background-color: rgb(178, 255, 228); + display: block; +} +span.run29 { + background-color: rgb(178, 255, 225); + display: block; +} +span.run30 { + background-color: rgb(178, 255, 221); + display: block; +} +span.run31 { + background-color: rgb(178, 255, 219); + display: block; +} +span.run32 { + background-color: rgb(178, 255, 216); + display: block; +} +span.run33 { + background-color: rgb(178, 255, 214); + display: block; +} +span.run34 { + background-color: rgb(178, 255, 211); + display: block; +} +span.run35 { + background-color: rgb(178, 255, 207); + display: block; +} +span.run36 { + background-color: rgb(178, 255, 205); + display: block; +} +span.run37 { + background-color: rgb(178, 255, 202); + display: block; +} +span.run38 { + background-color: rgb(178, 255, 200); + display: block; +} +span.run39 { + background-color: rgb(178, 255, 197); + display: block; +} +span.run40 { + background-color: rgb(178, 255, 193); + display: block; +} +span.run41 { + background-color: rgb(178, 255, 191); + display: block; +} +span.run42 { + background-color: rgb(178, 255, 188); + display: block; +} +span.run43 { + background-color: rgb(178, 255, 186); + display: block; +} +span.run44 { + background-color: rgb(178, 255, 183); + display: block; +} +span.run45 { + background-color: rgb(178, 255, 179); + display: block; +} +span.run46 { + background-color: rgb(179, 255, 178); + display: block; +} +span.run47 { + background-color: rgb(182, 255, 178); + display: block; +} +span.run48 { + background-color: rgb(184, 255, 178); + display: block; +} +span.run49 { + background-color: rgb(187, 255, 178); + display: block; +} +span.run50 { + background-color: rgb(191, 255, 178); + display: block; +} +span.run51 { + background-color: rgb(193, 255, 178); + display: block; +} +span.run52 { + background-color: rgb(196, 255, 178); + display: block; +} +span.run53 { + background-color: rgb(198, 255, 178); + display: block; +} +span.run54 { + background-color: rgb(201, 255, 178); + display: block; +} +span.run55 { + background-color: rgb(205, 255, 178); + display: block; +} +span.run56 { + background-color: rgb(207, 255, 178); + display: block; +} +span.run57 { + background-color: rgb(210, 255, 178); + display: block; +} +span.run58 { + background-color: rgb(212, 255, 178); + display: block; +} +span.run59 { + background-color: rgb(215, 255, 178); + display: block; +} +span.run60 { + background-color: rgb(219, 255, 178); + display: block; +} +span.run61 { + background-color: rgb(221, 255, 178); + display: block; +} +span.run62 { + background-color: rgb(224, 255, 178); + display: block; +} +span.run63 { + background-color: rgb(226, 255, 178); + display: block; +} +span.run64 { + background-color: rgb(229, 255, 178); + display: block; +} +span.run65 { + background-color: rgb(233, 255, 178); + display: block; +} +span.run66 { + background-color: rgb(235, 255, 178); + display: block; +} +span.run67 { + background-color: rgb(238, 255, 178); + display: block; +} +span.run68 { + background-color: rgb(240, 255, 178); + display: block; +} +span.run69 { + background-color: rgb(243, 255, 178); + display: block; +} +span.run70 { + background-color: rgb(247, 255, 178); + display: block; +} +span.run71 { + background-color: rgb(249, 255, 178); + display: block; +} +span.run72 { + background-color: rgb(252, 255, 178); + display: block; +} +span.run73 { + background-color: rgb(255, 255, 178); + display: block; +} +span.run74 { + background-color: rgb(255, 252, 178); + display: block; +} +span.run75 { + background-color: rgb(255, 248, 178); + display: block; +} +span.run76 { + background-color: rgb(255, 246, 178); + display: block; +} +span.run77 { + background-color: rgb(255, 243, 178); + display: block; +} +span.run78 { + background-color: rgb(255, 240, 178); + display: block; +} +span.run79 { + background-color: rgb(255, 238, 178); + display: block; +} +span.run80 { + background-color: rgb(255, 234, 178); + display: block; +} +span.run81 { + background-color: rgb(255, 232, 178); + display: block; +} +span.run82 { + background-color: rgb(255, 229, 178); + display: block; +} +span.run83 { + background-color: rgb(255, 226, 178); + display: block; +} +span.run84 { + background-color: rgb(255, 224, 178); + display: block; +} +span.run85 { + background-color: rgb(255, 220, 178); + display: block; +} +span.run86 { + background-color: rgb(255, 218, 178); + display: block; +} +span.run87 { + background-color: rgb(255, 215, 178); + display: block; +} +span.run88 { + background-color: rgb(255, 212, 178); + display: block; +} +span.run89 { + background-color: rgb(255, 210, 178); + display: block; +} +span.run90 { + background-color: rgb(255, 206, 178); + display: block; +} +span.run91 { + background-color: rgb(255, 204, 178); + display: block; +} +span.run92 { + background-color: rgb(255, 201, 178); + display: block; +} +span.run93 { + background-color: rgb(255, 198, 178); + display: block; +} +span.run94 { + background-color: rgb(255, 196, 178); + display: block; +} +span.run95 { + background-color: rgb(255, 192, 178); + display: block; +} +span.run96 { + background-color: rgb(255, 189, 178); + display: block; +} +span.run97 { + background-color: rgb(255, 187, 178); + display: block; +} +span.run98 { + background-color: rgb(255, 184, 178); + display: block; +} +span.run99 { + background-color: rgb(255, 182, 178); + display: block; +} +span.run100 { + background-color: rgb(255, 178, 178); + display: block; +} +pre { + white-space: pre-wrap; /* CSS2.1 compliant */ + white-space: -moz-pre-wrap; /* Mozilla-based browsers */ + white-space: -o-pre-wrap; /* Opera 7+ */ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/init.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,33 @@ +require 'redmine' +require 'embedded' + +Redmine::Plugin.register :embedded do + name 'Embedded' + author 'Jean-Philippe Lang' + description 'Embed various documentations in your projects' + version '0.0.1' + settings :default => { 'path' => '/var/doc/{PROJECT}/html', + 'index' => 'main.html overview-summary.html index.html', + 'extensions' => 'html png gif', + 'template' => '', + 'encoding' => '', + 'menu' => 'Embedded' }, + :partial => 'settings/embedded' + + project_module :embedded do + permission :view_embedded_doc, {:embedded => :index} + end + + menu :project_menu, :embedded, { :controller => 'embedded', :action => 'index', :path => nil }, + :caption => Proc.new { Setting.plugin_embedded['menu'] }, + :if => Proc.new { !Setting.plugin_embedded['menu'].blank? } +end + +# Routes +class << ActionController::Routing::Routes;self;end.class_eval do + define_method :clear!, lambda {} +end + +ActionController::Routing::Routes.draw do |map| + map.connect 'embedded/:id/*path', :controller => 'embedded', :action => 'index' +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/lib/embedded.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,64 @@ +# Redmine - project management software +# Copyright (C) 2008 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +module Redmine + module Plugins + module Embedded + class << self + + # Returns an Array of available templates + def available_templates + assets_by_template.keys.sort + end + + # Returns the assets for a given template + def assets(template) + assets_by_template.has_key?(template) ? assets_by_template[template] : [] + end + + def detect_template_from_path(path) + t = path.to_s.split(%r{[/\\]}) & available_templates + t.empty? ? Setting.plugin_embedded['template'].to_s : t.first + end + + def valid_extension?(path) + extensions = Setting.plugin_embedded['extensions'].to_s.split.each(&:downcase) + extensions.include?(File.extname(path).downcase[1..-1]) + end + + private + + # A Hash of available assets by template + def assets_by_template + @@assets_by_template ||= scan_assets + end + + # Scans assets directory for templates + # and returns a Hash of available assets by template + def scan_assets + a = Hash.new {|h,k| h[k] = [] } + Dir.glob(File.join(File.dirname(__FILE__), '../assets/*/*.{css,js}')).each do |asset| + asset = File.basename(asset) + template = asset.gsub(%r{\.(js|css)$}, '') + a[template] << asset + end + a + end + end + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/test/fixtures/html/app-controllers-account_controller_rb.html Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,783 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'><head><title>app/controllers/account_controller.rb - C0 code coverage information</title> + <style type='text/css'>body { background-color: rgb(240, 240, 245); }</style> + <style type='text/css'>span.cross-ref-title { + font-size: 140%; +} +span.cross-ref a { + text-decoration: none; +} +span.cross-ref { + background-color:#f3f7fa; + border: 1px dashed #333; + margin: 1em; + padding: 0.5em; + overflow: hidden; +} +a.crossref-toggle { + text-decoration: none; +} +span.marked0 { + background-color: rgb(185, 210, 200); + display: block; +} +span.marked1 { + background-color: rgb(190, 215, 205); + display: block; +} +span.inferred0 { + background-color: rgb(175, 200, 200); + display: block; +} +span.inferred1 { + background-color: rgb(180, 205, 205); + display: block; +} +span.uncovered0 { + background-color: rgb(225, 110, 110); + display: block; +} +span.uncovered1 { + background-color: rgb(235, 120, 120); + display: block; +} +span.overview { + border-bottom: 8px solid black; +} +div.overview { + border-bottom: 8px solid black; +} +body { + font-family: verdana, arial, helvetica; +} +div.footer { + font-size: 68%; + margin-top: 1.5em; +} +h1, h2, h3, h4, h5, h6 { + margin-bottom: 0.5em; +} +h5 { + margin-top: 0.5em; +} +.hidden { + display: none; +} +div.separator { + height: 10px; +} +/* Commented out for better readability, esp. on IE */ +/* +table tr td, table tr th { + font-size: 68%; +} +td.value table tr td { + font-size: 11px; +} +*/ +table.percent_graph { + height: 12px; + border: #808080 1px solid; + empty-cells: show; +} +table.percent_graph td.covered { + height: 10px; + background: #00f000; +} +table.percent_graph td.uncovered { + height: 10px; + background: #e00000; +} +table.percent_graph td.NA { + height: 10px; + background: #eaeaea; +} +table.report { + border-collapse: collapse; + width: 100%; +} +table.report td.heading { + background: #dcecff; + border: #d0d0d0 1px solid; + font-weight: bold; + text-align: center; +} +table.report td.heading:hover { + background: #c0ffc0; +} +table.report td.text { + border: #d0d0d0 1px solid; +} +table.report td.value, +table.report td.lines_total, +table.report td.lines_code { + text-align: right; + border: #d0d0d0 1px solid; +} +table.report tr.light { + background-color: rgb(240, 240, 245); +} +table.report tr.dark { + background-color: rgb(230, 230, 235); +} +</style> + <script type='text/javascript'> +// <![CDATA[ + function toggleCode( id ) { + if ( document.getElementById ) + elem = document.getElementById( id ); + else if ( document.all ) + elem = eval( "document.all." + id ); + else + return false; + + elemStyle = elem.style; + + if ( elemStyle.display != "block" ) { + elemStyle.display = "block" + } else { + elemStyle.display = "none" + } + + return true; + } + + // Make cross-references hidden by default + document.writeln( "<style type=\"text/css\">span.cross-ref { display: none }</style>" ) + // ]]> +</script> + <style type='text/css'>span.run0 { + background-color: rgb(178, 204, 255); + display: block; +} +span.run1 { + background-color: rgb(178, 206, 255); + display: block; +} +span.run2 { + background-color: rgb(178, 209, 255); + display: block; +} +span.run3 { + background-color: rgb(178, 211, 255); + display: block; +} +span.run4 { + background-color: rgb(178, 214, 255); + display: block; +} +span.run5 { + background-color: rgb(178, 218, 255); + display: block; +} +span.run6 { + background-color: rgb(178, 220, 255); + display: block; +} +span.run7 { + background-color: rgb(178, 223, 255); + display: block; +} +span.run8 { + background-color: rgb(178, 225, 255); + display: block; +} +span.run9 { + background-color: rgb(178, 228, 255); + display: block; +} +span.run10 { + background-color: rgb(178, 232, 255); + display: block; +} +span.run11 { + background-color: rgb(178, 234, 255); + display: block; +} +span.run12 { + background-color: rgb(178, 237, 255); + display: block; +} +span.run13 { + background-color: rgb(178, 239, 255); + display: block; +} +span.run14 { + background-color: rgb(178, 242, 255); + display: block; +} +span.run15 { + background-color: rgb(178, 246, 255); + display: block; +} +span.run16 { + background-color: rgb(178, 248, 255); + display: block; +} +span.run17 { + background-color: rgb(178, 251, 255); + display: block; +} +span.run18 { + background-color: rgb(178, 253, 255); + display: block; +} +span.run19 { + background-color: rgb(178, 255, 253); + display: block; +} +span.run20 { + background-color: rgb(178, 255, 249); + display: block; +} +span.run21 { + background-color: rgb(178, 255, 247); + display: block; +} +span.run22 { + background-color: rgb(178, 255, 244); + display: block; +} +span.run23 { + background-color: rgb(178, 255, 242); + display: block; +} +span.run24 { + background-color: rgb(178, 255, 239); + display: block; +} +span.run25 { + background-color: rgb(178, 255, 235); + display: block; +} +span.run26 { + background-color: rgb(178, 255, 233); + display: block; +} +span.run27 { + background-color: rgb(178, 255, 230); + display: block; +} +span.run28 { + background-color: rgb(178, 255, 228); + display: block; +} +span.run29 { + background-color: rgb(178, 255, 225); + display: block; +} +span.run30 { + background-color: rgb(178, 255, 221); + display: block; +} +span.run31 { + background-color: rgb(178, 255, 219); + display: block; +} +span.run32 { + background-color: rgb(178, 255, 216); + display: block; +} +span.run33 { + background-color: rgb(178, 255, 214); + display: block; +} +span.run34 { + background-color: rgb(178, 255, 211); + display: block; +} +span.run35 { + background-color: rgb(178, 255, 207); + display: block; +} +span.run36 { + background-color: rgb(178, 255, 205); + display: block; +} +span.run37 { + background-color: rgb(178, 255, 202); + display: block; +} +span.run38 { + background-color: rgb(178, 255, 200); + display: block; +} +span.run39 { + background-color: rgb(178, 255, 197); + display: block; +} +span.run40 { + background-color: rgb(178, 255, 193); + display: block; +} +span.run41 { + background-color: rgb(178, 255, 191); + display: block; +} +span.run42 { + background-color: rgb(178, 255, 188); + display: block; +} +span.run43 { + background-color: rgb(178, 255, 186); + display: block; +} +span.run44 { + background-color: rgb(178, 255, 183); + display: block; +} +span.run45 { + background-color: rgb(178, 255, 179); + display: block; +} +span.run46 { + background-color: rgb(179, 255, 178); + display: block; +} +span.run47 { + background-color: rgb(182, 255, 178); + display: block; +} +span.run48 { + background-color: rgb(184, 255, 178); + display: block; +} +span.run49 { + background-color: rgb(187, 255, 178); + display: block; +} +span.run50 { + background-color: rgb(191, 255, 178); + display: block; +} +span.run51 { + background-color: rgb(193, 255, 178); + display: block; +} +span.run52 { + background-color: rgb(196, 255, 178); + display: block; +} +span.run53 { + background-color: rgb(198, 255, 178); + display: block; +} +span.run54 { + background-color: rgb(201, 255, 178); + display: block; +} +span.run55 { + background-color: rgb(205, 255, 178); + display: block; +} +span.run56 { + background-color: rgb(207, 255, 178); + display: block; +} +span.run57 { + background-color: rgb(210, 255, 178); + display: block; +} +span.run58 { + background-color: rgb(212, 255, 178); + display: block; +} +span.run59 { + background-color: rgb(215, 255, 178); + display: block; +} +span.run60 { + background-color: rgb(219, 255, 178); + display: block; +} +span.run61 { + background-color: rgb(221, 255, 178); + display: block; +} +span.run62 { + background-color: rgb(224, 255, 178); + display: block; +} +span.run63 { + background-color: rgb(226, 255, 178); + display: block; +} +span.run64 { + background-color: rgb(229, 255, 178); + display: block; +} +span.run65 { + background-color: rgb(233, 255, 178); + display: block; +} +span.run66 { + background-color: rgb(235, 255, 178); + display: block; +} +span.run67 { + background-color: rgb(238, 255, 178); + display: block; +} +span.run68 { + background-color: rgb(240, 255, 178); + display: block; +} +span.run69 { + background-color: rgb(243, 255, 178); + display: block; +} +span.run70 { + background-color: rgb(247, 255, 178); + display: block; +} +span.run71 { + background-color: rgb(249, 255, 178); + display: block; +} +span.run72 { + background-color: rgb(252, 255, 178); + display: block; +} +span.run73 { + background-color: rgb(255, 255, 178); + display: block; +} +span.run74 { + background-color: rgb(255, 252, 178); + display: block; +} +span.run75 { + background-color: rgb(255, 248, 178); + display: block; +} +span.run76 { + background-color: rgb(255, 246, 178); + display: block; +} +span.run77 { + background-color: rgb(255, 243, 178); + display: block; +} +span.run78 { + background-color: rgb(255, 240, 178); + display: block; +} +span.run79 { + background-color: rgb(255, 238, 178); + display: block; +} +span.run80 { + background-color: rgb(255, 234, 178); + display: block; +} +span.run81 { + background-color: rgb(255, 232, 178); + display: block; +} +span.run82 { + background-color: rgb(255, 229, 178); + display: block; +} +span.run83 { + background-color: rgb(255, 226, 178); + display: block; +} +span.run84 { + background-color: rgb(255, 224, 178); + display: block; +} +span.run85 { + background-color: rgb(255, 220, 178); + display: block; +} +span.run86 { + background-color: rgb(255, 218, 178); + display: block; +} +span.run87 { + background-color: rgb(255, 215, 178); + display: block; +} +span.run88 { + background-color: rgb(255, 212, 178); + display: block; +} +span.run89 { + background-color: rgb(255, 210, 178); + display: block; +} +span.run90 { + background-color: rgb(255, 206, 178); + display: block; +} +span.run91 { + background-color: rgb(255, 204, 178); + display: block; +} +span.run92 { + background-color: rgb(255, 201, 178); + display: block; +} +span.run93 { + background-color: rgb(255, 198, 178); + display: block; +} +span.run94 { + background-color: rgb(255, 196, 178); + display: block; +} +span.run95 { + background-color: rgb(255, 192, 178); + display: block; +} +span.run96 { + background-color: rgb(255, 189, 178); + display: block; +} +span.run97 { + background-color: rgb(255, 187, 178); + display: block; +} +span.run98 { + background-color: rgb(255, 184, 178); + display: block; +} +span.run99 { + background-color: rgb(255, 182, 178); + display: block; +} +span.run100 { + background-color: rgb(255, 178, 178); + display: block; +} +</style> + </head> + <body><h3>C0 code coverage information</h3> + <p>Generated on Tue Jun 24 21:43:53 +0200 2008 with <a href='http://eigenclass.org/hiki/rcov'>rcov 0.8.1.2</a> + </p> + <hr/> + <pre><span class='marked0'>Code reported as executed by Ruby looks like this... +</span><span class='marked1'>and this: this line is also marked as covered. +</span><span class='inferred0'>Lines considered as run by rcov, but not reported by Ruby, look like this, +</span><span class='inferred1'>and this: these lines were inferred by rcov (using simple heuristics). +</span><span class='uncovered0'>Finally, here's a line marked as not executed. +</span></pre> +<table class='report'><thead><tr><td class='heading'>Name</td> + <td class='heading'>Total lines</td> + <td class='heading'>Lines of code</td> + <td class='heading'>Total coverage</td> + <td class='heading'>Code coverage</td> + </tr> + </thead> + <tbody><tr class='light'><td><a href='app-controllers-account_controller_rb.html'>app/controllers/account_controller.rb</a> + </td> + <td class='lines_total'><tt>173</tt> + </td> + <td class='lines_code'><tt>129</tt> + </td> + <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_total'>98.8%</tt> + </td> + <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='99'/> + <td class='uncovered' width='1'/> + </tr> + </table> + </td> + </tr> + </table> + </td> + <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_code'>98.4%</tt> + </td> + <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='98'/> + <td class='uncovered' width='2'/> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + </tbody> + </table> +<pre><span class="inferred0"><a name="line1"></a> 1 # redMine - project management software +</span><span class="inferred1"><a name="line2"></a> 2 # Copyright (C) 2006-2007 Jean-Philippe Lang +</span><span class="inferred0"><a name="line3"></a> 3 # +</span><span class="inferred1"><a name="line4"></a> 4 # This program is free software; you can redistribute it and/or +</span><span class="inferred0"><a name="line5"></a> 5 # modify it under the terms of the GNU General Public License +</span><span class="inferred1"><a name="line6"></a> 6 # as published by the Free Software Foundation; either version 2 +</span><span class="inferred0"><a name="line7"></a> 7 # of the License, or (at your option) any later version. +</span><span class="inferred1"><a name="line8"></a> 8 # +</span><span class="inferred0"><a name="line9"></a> 9 # This program is distributed in the hope that it will be useful, +</span><span class="inferred1"><a name="line10"></a> 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of +</span><span class="inferred0"><a name="line11"></a> 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +</span><span class="inferred1"><a name="line12"></a> 12 # GNU General Public License for more details. +</span><span class="inferred0"><a name="line13"></a> 13 # +</span><span class="inferred1"><a name="line14"></a> 14 # You should have received a copy of the GNU General Public License +</span><span class="inferred0"><a name="line15"></a> 15 # along with this program; if not, write to the Free Software +</span><span class="inferred1"><a name="line16"></a> 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +</span><span class="inferred0"><a name="line17"></a> 17 +</span><span class="marked1"><a name="line18"></a> 18 class AccountController < ApplicationController +</span><span class="marked0"><a name="line19"></a> 19 layout 'base' +</span><span class="marked1"><a name="line20"></a> 20 helper :custom_fields +</span><span class="marked0"><a name="line21"></a> 21 include CustomFieldsHelper +</span><span class="inferred1"><a name="line22"></a> 22 +</span><span class="inferred0"><a name="line23"></a> 23 # prevents login action to be filtered by check_if_login_required application scope filter +</span><span class="marked1"><a name="line24"></a> 24 skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register, :activate] +</span><span class="inferred0"><a name="line25"></a> 25 +</span><span class="inferred1"><a name="line26"></a> 26 # Show user's account +</span><span class="marked0"><a name="line27"></a> 27 def show +</span><span class="marked1"><a name="line28"></a> 28 @user = User.find_active(params[:id]) +</span><span class="marked0"><a name="line29"></a> 29 @custom_values = @user.custom_values.find(:all, :include => :custom_field) +</span><span class="inferred1"><a name="line30"></a> 30 +</span><span class="inferred0"><a name="line31"></a> 31 # show only public projects and private projects that the logged in user is also a member of +</span><span class="marked1"><a name="line32"></a> 32 @memberships = @user.memberships.select do |membership| +</span><span class="marked0"><a name="line33"></a> 33 membership.project.is_public? || (User.current.member_of?(membership.project)) +</span><span class="inferred1"><a name="line34"></a> 34 end +</span><span class="inferred0"><a name="line35"></a> 35 rescue ActiveRecord::RecordNotFound +</span><span class="marked1"><a name="line36"></a> 36 render_404 +</span><span class="marked0"><a name="line37"></a> 37 end +</span><span class="inferred1"><a name="line38"></a> 38 +</span><span class="inferred0"><a name="line39"></a> 39 # Login request and validation +</span><span class="marked1"><a name="line40"></a> 40 def login +</span><span class="marked0"><a name="line41"></a> 41 if request.get? +</span><span class="inferred1"><a name="line42"></a> 42 # Logout user +</span><span class="marked0"><a name="line43"></a> 43 self.logged_user = nil +</span><span class="inferred1"><a name="line44"></a> 44 else +</span><span class="inferred0"><a name="line45"></a> 45 # Authenticate user +</span><span class="marked1"><a name="line46"></a> 46 user = User.try_to_login(params[:username], params[:password]) +</span><span class="marked0"><a name="line47"></a> 47 if user +</span><span class="marked1"><a name="line48"></a> 48 self.logged_user = user +</span><span class="inferred0"><a name="line49"></a> 49 # generate a key and set cookie if autologin +</span><span class="marked1"><a name="line50"></a> 50 if params[:autologin] && Setting.autologin? +</span><span class="marked0"><a name="line51"></a> 51 token = Token.create(:user => user, :action => 'autologin') +</span><span class="marked1"><a name="line52"></a> 52 cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now } +</span><span class="inferred0"><a name="line53"></a> 53 end +</span><span class="marked1"><a name="line54"></a> 54 redirect_back_or_default :controller => 'my', :action => 'page' +</span><span class="inferred0"><a name="line55"></a> 55 else +</span><span class="marked1"><a name="line56"></a> 56 flash.now[:error] = l(:notice_account_invalid_creditentials) +</span><span class="inferred0"><a name="line57"></a> 57 end +</span><span class="inferred1"><a name="line58"></a> 58 end +</span><span class="uncovered0"><a name="line59"></a> 59 rescue User::OnTheFlyCreationFailure +</span><span class="uncovered1"><a name="line60"></a> 60 flash.now[:error] = 'Redmine could not retrieve the required information from the LDAP to create your account. Please, contact your Redmine administrator.' +</span><span class="marked0"><a name="line61"></a> 61 end +</span><span class="inferred1"><a name="line62"></a> 62 +</span><span class="inferred0"><a name="line63"></a> 63 # Log out current user and redirect to welcome page +</span><span class="marked1"><a name="line64"></a> 64 def logout +</span><span class="marked0"><a name="line65"></a> 65 cookies.delete :autologin +</span><span class="marked1"><a name="line66"></a> 66 Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin']) if User.current.logged? +</span><span class="marked0"><a name="line67"></a> 67 self.logged_user = nil +</span><span class="marked1"><a name="line68"></a> 68 redirect_to home_url +</span><span class="inferred0"><a name="line69"></a> 69 end +</span><span class="inferred1"><a name="line70"></a> 70 +</span><span class="inferred0"><a name="line71"></a> 71 # Enable user to choose a new password +</span><span class="marked1"><a name="line72"></a> 72 def lost_password +</span><span class="marked0"><a name="line73"></a> 73 redirect_to(home_url) && return unless Setting.lost_password? +</span><span class="marked1"><a name="line74"></a> 74 if params[:token] +</span><span class="marked0"><a name="line75"></a> 75 @token = Token.find_by_action_and_value("recovery", params[:token]) +</span><span class="marked1"><a name="line76"></a> 76 redirect_to(home_url) && return unless @token and !@token.expired? +</span><span class="marked0"><a name="line77"></a> 77 @user = @token.user +</span><span class="marked1"><a name="line78"></a> 78 if request.post? +</span><span class="marked0"><a name="line79"></a> 79 @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation] +</span><span class="marked1"><a name="line80"></a> 80 if @user.save +</span><span class="marked0"><a name="line81"></a> 81 @token.destroy +</span><span class="marked1"><a name="line82"></a> 82 flash[:notice] = l(:notice_account_password_updated) +</span><span class="marked0"><a name="line83"></a> 83 redirect_to :action => 'login' +</span><span class="marked1"><a name="line84"></a> 84 return +</span><span class="inferred0"><a name="line85"></a> 85 end +</span><span class="inferred1"><a name="line86"></a> 86 end +</span><span class="marked0"><a name="line87"></a> 87 render :template => "account/password_recovery" +</span><span class="marked1"><a name="line88"></a> 88 return +</span><span class="inferred0"><a name="line89"></a> 89 else +</span><span class="marked1"><a name="line90"></a> 90 if request.post? +</span><span class="marked0"><a name="line91"></a> 91 user = User.find_by_mail(params[:mail]) +</span><span class="inferred1"><a name="line92"></a> 92 # user not found in db +</span><span class="marked0"><a name="line93"></a> 93 flash.now[:error] = l(:notice_account_unknown_email) and return unless user +</span><span class="inferred1"><a name="line94"></a> 94 # user uses an external authentification +</span><span class="marked0"><a name="line95"></a> 95 flash.now[:error] = l(:notice_can_t_change_password) and return if user.auth_source_id +</span><span class="inferred1"><a name="line96"></a> 96 # create a new token for password recovery +</span><span class="marked0"><a name="line97"></a> 97 token = Token.new(:user => user, :action => "recovery") +</span><span class="marked1"><a name="line98"></a> 98 if token.save +</span><span class="marked0"><a name="line99"></a> 99 Mailer.deliver_lost_password(token) +</span><span class="marked1"><a name="line100"></a>100 flash[:notice] = l(:notice_account_lost_email_sent) +</span><span class="marked0"><a name="line101"></a>101 redirect_to :action => 'login' +</span><span class="marked1"><a name="line102"></a>102 return +</span><span class="inferred0"><a name="line103"></a>103 end +</span><span class="inferred1"><a name="line104"></a>104 end +</span><span class="inferred0"><a name="line105"></a>105 end +</span><span class="inferred1"><a name="line106"></a>106 end +</span><span class="inferred0"><a name="line107"></a>107 +</span><span class="inferred1"><a name="line108"></a>108 # User self-registration +</span><span class="marked0"><a name="line109"></a>109 def register +</span><span class="marked1"><a name="line110"></a>110 redirect_to(home_url) && return unless Setting.self_registration? +</span><span class="marked0"><a name="line111"></a>111 if request.get? +</span><span class="marked1"><a name="line112"></a>112 @user = User.new(:language => Setting.default_language) +</span><span class="inferred0"><a name="line113"></a>113 else +</span><span class="marked1"><a name="line114"></a>114 @user = User.new(params[:user]) +</span><span class="marked0"><a name="line115"></a>115 @user.admin = false +</span><span class="marked1"><a name="line116"></a>116 @user.login = params[:user][:login] +</span><span class="marked0"><a name="line117"></a>117 @user.status = User::STATUS_REGISTERED +</span><span class="marked1"><a name="line118"></a>118 @user.password, @user.password_confirmation = params[:password], params[:password_confirmation] +</span><span class="marked0"><a name="line119"></a>119 case Setting.self_registration +</span><span class="marked1"><a name="line120"></a>120 when '1' +</span><span class="inferred0"><a name="line121"></a>121 # Email activation +</span><span class="marked1"><a name="line122"></a>122 token = Token.new(:user => @user, :action => "register") +</span><span class="marked0"><a name="line123"></a>123 if @user.save and token.save +</span><span class="marked1"><a name="line124"></a>124 Mailer.deliver_register(token) +</span><span class="marked0"><a name="line125"></a>125 flash[:notice] = l(:notice_account_register_done) +</span><span class="marked1"><a name="line126"></a>126 redirect_to :action => 'login' +</span><span class="inferred0"><a name="line127"></a>127 end +</span><span class="marked1"><a name="line128"></a>128 when '3' +</span><span class="inferred0"><a name="line129"></a>129 # Automatic activation +</span><span class="marked1"><a name="line130"></a>130 @user.status = User::STATUS_ACTIVE +</span><span class="marked0"><a name="line131"></a>131 if @user.save +</span><span class="marked1"><a name="line132"></a>132 self.logged_user = @user +</span><span class="marked0"><a name="line133"></a>133 flash[:notice] = l(:notice_account_activated) +</span><span class="marked1"><a name="line134"></a>134 redirect_to :controller => 'my', :action => 'account' +</span><span class="inferred0"><a name="line135"></a>135 end +</span><span class="inferred1"><a name="line136"></a>136 else +</span><span class="inferred0"><a name="line137"></a>137 # Manual activation by the administrator +</span><span class="marked1"><a name="line138"></a>138 if @user.save +</span><span class="inferred0"><a name="line139"></a>139 # Sends an email to the administrators +</span><span class="marked1"><a name="line140"></a>140 Mailer.deliver_account_activation_request(@user) +</span><span class="marked0"><a name="line141"></a>141 flash[:notice] = l(:notice_account_pending) +</span><span class="marked1"><a name="line142"></a>142 redirect_to :action => 'login' +</span><span class="inferred0"><a name="line143"></a>143 end +</span><span class="inferred1"><a name="line144"></a>144 end +</span><span class="inferred0"><a name="line145"></a>145 end +</span><span class="inferred1"><a name="line146"></a>146 end +</span><span class="inferred0"><a name="line147"></a>147 +</span><span class="inferred1"><a name="line148"></a>148 # Token based account activation +</span><span class="marked0"><a name="line149"></a>149 def activate +</span><span class="marked1"><a name="line150"></a>150 redirect_to(home_url) && return unless Setting.self_registration? && params[:token] +</span><span class="marked0"><a name="line151"></a>151 token = Token.find_by_action_and_value('register', params[:token]) +</span><span class="marked1"><a name="line152"></a>152 redirect_to(home_url) && return unless token and !token.expired? +</span><span class="marked0"><a name="line153"></a>153 user = token.user +</span><span class="marked1"><a name="line154"></a>154 redirect_to(home_url) && return unless user.status == User::STATUS_REGISTERED +</span><span class="marked0"><a name="line155"></a>155 user.status = User::STATUS_ACTIVE +</span><span class="marked1"><a name="line156"></a>156 if user.save +</span><span class="marked0"><a name="line157"></a>157 token.destroy +</span><span class="marked1"><a name="line158"></a>158 flash[:notice] = l(:notice_account_activated) +</span><span class="inferred0"><a name="line159"></a>159 end +</span><span class="marked1"><a name="line160"></a>160 redirect_to :action => 'login' +</span><span class="inferred0"><a name="line161"></a>161 end +</span><span class="inferred1"><a name="line162"></a>162 +</span><span class="marked0"><a name="line163"></a>163 private +</span><span class="marked1"><a name="line164"></a>164 def logged_user=(user) +</span><span class="marked0"><a name="line165"></a>165 if user && user.is_a?(User) +</span><span class="marked1"><a name="line166"></a>166 User.current = user +</span><span class="marked0"><a name="line167"></a>167 session[:user_id] = user.id +</span><span class="inferred1"><a name="line168"></a>168 else +</span><span class="marked0"><a name="line169"></a>169 User.current = User.anonymous +</span><span class="marked1"><a name="line170"></a>170 session[:user_id] = nil +</span><span class="inferred0"><a name="line171"></a>171 end +</span><span class="marked1"><a name="line172"></a>172 end +</span><span class="inferred0"><a name="line173"></a>173 end +</span></pre><hr/> + <p>Generated using the <a href='http://eigenclass.org/hiki.rb?rcov'>rcov code coverage analysis tool for Ruby</a> + version 0.8.1.2.</p> +<p><a href='http://validator.w3.org/check/referer'><img src='http://www.w3.org/Icons/valid-xhtml10' height='31' alt='Valid XHTML 1.0!' width='88'/> + </a> + <a href='http://jigsaw.w3.org/css-validator/check/referer'><img src='http://jigsaw.w3.org/css-validator/images/vcss' alt='Valid CSS!' style='border:0;width:88px;height:31px'/> + </a> + </p> + </body> + </html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/test/fixtures/html/index.html Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,306 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'><head><title>C0 code coverage information</title> + <style type='text/css'>body { background-color: rgb(240, 240, 245); }</style> + <style type='text/css'>span.cross-ref-title { + font-size: 140%; +} +span.cross-ref a { + text-decoration: none; +} +span.cross-ref { + background-color:#f3f7fa; + border: 1px dashed #333; + margin: 1em; + padding: 0.5em; + overflow: hidden; +} +a.crossref-toggle { + text-decoration: none; +} +span.marked0 { + background-color: rgb(185, 210, 200); + display: block; +} +span.marked1 { + background-color: rgb(190, 215, 205); + display: block; +} +span.inferred0 { + background-color: rgb(175, 200, 200); + display: block; +} +span.inferred1 { + background-color: rgb(180, 205, 205); + display: block; +} +span.uncovered0 { + background-color: rgb(225, 110, 110); + display: block; +} +span.uncovered1 { + background-color: rgb(235, 120, 120); + display: block; +} +span.overview { + border-bottom: 8px solid black; +} +div.overview { + border-bottom: 8px solid black; +} +body { + font-family: verdana, arial, helvetica; +} +div.footer { + font-size: 68%; + margin-top: 1.5em; +} +h1, h2, h3, h4, h5, h6 { + margin-bottom: 0.5em; +} +h5 { + margin-top: 0.5em; +} +.hidden { + display: none; +} +div.separator { + height: 10px; +} +/* Commented out for better readability, esp. on IE */ +/* +table tr td, table tr th { + font-size: 68%; +} +td.value table tr td { + font-size: 11px; +} +*/ +table.percent_graph { + height: 12px; + border: #808080 1px solid; + empty-cells: show; +} +table.percent_graph td.covered { + height: 10px; + background: #00f000; +} +table.percent_graph td.uncovered { + height: 10px; + background: #e00000; +} +table.percent_graph td.NA { + height: 10px; + background: #eaeaea; +} +table.report { + border-collapse: collapse; + width: 100%; +} +table.report td.heading { + background: #dcecff; + border: #d0d0d0 1px solid; + font-weight: bold; + text-align: center; +} +table.report td.heading:hover { + background: #c0ffc0; +} +table.report td.text { + border: #d0d0d0 1px solid; +} +table.report td.value, +table.report td.lines_total, +table.report td.lines_code { + text-align: right; + border: #d0d0d0 1px solid; +} +table.report tr.light { + background-color: rgb(240, 240, 245); +} +table.report tr.dark { + background-color: rgb(230, 230, 235); +} +</style> + <script type='text/javascript'> +// <![CDATA[ + function toggleCode( id ) { + if ( document.getElementById ) + elem = document.getElementById( id ); + else if ( document.all ) + elem = eval( "document.all." + id ); + else + return false; + + elemStyle = elem.style; + + if ( elemStyle.display != "block" ) { + elemStyle.display = "block" + } else { + elemStyle.display = "none" + } + + return true; + } + + // Make cross-references hidden by default + document.writeln( "<style type=\"text/css\">span.cross-ref { display: none }</style>" ) + // ]]> +</script> + </head> + <body><h3>C0 code coverage information</h3> + <p>Generated on Tue Jun 24 21:43:50 +0200 2008 with <a href='http://eigenclass.org/hiki/rcov'>rcov 0.8.1.2</a> + </p> + <hr/> + <table class='report'><thead><tr><td class='heading'>Name</td> + <td class='heading'>Total lines</td> + <td class='heading'>Lines of code</td> + <td class='heading'>Total coverage</td> + <td class='heading'>Code coverage</td> + </tr> + </thead> + <tbody><tr class='light'><td>TOTAL</td> + <td class='lines_total'><tt>13757</tt> + </td> + <td class='lines_code'><tt>9314</tt> + </td> + <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_total'>90.7%</tt> + </td> + <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='91'/> + <td class='uncovered' width='9'/> + </tr> + </table> + </td> + </tr> + </table> + </td> + <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_code'>86.9%</tt> + </td> + <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='87'/> + <td class='uncovered' width='13'/> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + <tr class='dark'><td><a href='app-apis-sys_api_rb.html'>app/apis/sys_api.rb</a> + </td> + <td class='lines_total'><tt>25</tt> + </td> + <td class='lines_code'><tt>8</tt> + </td> + <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_total'>100.0%</tt> + </td> + <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='100'/> + <td class='uncovered' width='0'/> + </tr> + </table> + </td> + </tr> + </table> + </td> + <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_code'>100.0%</tt> + </td> + <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='100'/> + <td class='uncovered' width='0'/> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + <tr class='light'><td><a href='app-controllers-account_controller_rb.html'>app/controllers/account_controller.rb</a> + </td> + <td class='lines_total'><tt>173</tt> + </td> + <td class='lines_code'><tt>129</tt> + </td> + <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_total'>98.8%</tt> + </td> + <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='99'/> + <td class='uncovered' width='1'/> + </tr> + </table> + </td> + </tr> + </table> + </td> + <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_code'>98.4%</tt> + </td> + <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='98'/> + <td class='uncovered' width='2'/> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + <tr class='dark'><td><a href='app-controllers-admin_controller_rb.html'>app/controllers/admin_controller.rb</a> + </td> + <td class='lines_total'><tt>86</tt> + </td> + <td class='lines_code'><tt>57</tt> + </td> + <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_total'>91.9%</tt> + </td> + <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='92'/> + <td class='uncovered' width='8'/> + </tr> + </table> + </td> + </tr> + </table> + </td> + <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_code'>87.7%</tt> + </td> + <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='88'/> + <td class='uncovered' width='12'/> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + <tr class='light'><td><a href='app-controllers-application_rb.html'>app/controllers/application.rb</a> + </td> + <td class='lines_total'><tt>222</tt> + </td> + <td class='lines_code'><tt>162</tt> + </td> + <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_total'>89.6%</tt> + </td> + <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='90'/> + <td class='uncovered' width='10'/> + </tr> + </table> + </td> + </tr> + </table> + </td> + <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_code'>87.0%</tt> + </td> + <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='87'/> + <td class='uncovered' width='13'/> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + </tbody> + </table> +<hr/> + <p>Generated using the <a href='http://eigenclass.org/hiki.rb?rcov'>rcov code coverage analysis tool for Ruby</a> + version 0.8.1.2.</p> +<p><a href='http://validator.w3.org/check/referer'><img src='http://www.w3.org/Icons/valid-xhtml11' height='31' alt='Valid XHTML 1.1!' width='88'/> + </a> + <a href='http://jigsaw.w3.org/css-validator/check/referer'><img src='http://jigsaw.w3.org/css-validator/images/vcss' alt='Valid CSS!' style='border:0;width:88px;height:31px'/> + </a> + </p> + </body> + </html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/test/fixtures/html/misc/misc.html Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,1 @@ +<b>Misc file</b>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/test/fixtures/html/misc/misc.txt Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,1 @@ +Misc file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/test/functional/embedded_controller_test.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,63 @@ +# Redmine - project management software +# Copyright (C) 2008 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.dirname(__FILE__) + '/../test_helper' + +class EmbeddedControllerTest < ActionController::TestCase + fixtures :projects, :enabled_modules, :users, :roles, :members + + def setup + fixtures_path = File.dirname(__FILE__) + '/../fixtures/html' + + Setting.plugin_embedded = { 'path' => fixtures_path, + 'index' => 'main.html overview-summary.html index.html', + 'extensions' => 'html png gif', + 'template' => '', + 'encoding' => '', + 'menu' => 'Embedded' } + + Project.find(1).enabled_modules << EnabledModule.new(:name => 'embedded') + + anonymous = Role.anonymous + anonymous.permissions += [:view_embedded_doc] + assert anonymous.save + end + + def test_get_root_should_redirect_to_index_file + get :index, :id => 'ecookbook' + assert_redirected_to :path => ['index.html'] + end + + def test_get_index_file + get :index, :id => 'ecookbook', :path => ['index.html'] + assert_response :success + assert_template 'index' + assert_tag :h3, :content => 'C0 code coverage information' + end + + def test_get_subdirectory_file + get :index, :id => 'ecookbook', :path => ['misc', 'misc.html'] + assert_response :success + assert_template 'index' + assert_tag :b, :content => 'Misc file' + end + + def test_get_invalid_extension_should_be_denied + get :index, :id => 'ecookbook', :path => ['misc', 'misc.txt'] + assert_response 500 + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/test/test_helper.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,38 @@ +ENV["RAILS_ENV"] ||= "test" +require File.expand_path(File.dirname(__FILE__) + "/../../../../config/environment") +require 'test_help' + +class Test::Unit::TestCase + # Transactional fixtures accelerate your tests by wrapping each test method + # in a transaction that's rolled back on completion. This ensures that the + # test database remains unchanged so your fixtures don't have to be reloaded + # between every test method. Fewer database queries means faster tests. + # + # Read Mike Clark's excellent walkthrough at + # http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting + # + # Every Active Record database supports transactions except MyISAM tables + # in MySQL. Turn off transactional fixtures in this case; however, if you + # don't care one way or the other, switching from MyISAM to InnoDB tables + # is recommended. + # + # The only drawback to using transactional fixtures is when you actually + # need to test transactions. Since your test is bracketed by a transaction, + # any transactions started in your code will be automatically rolled back. + self.use_transactional_fixtures = true + + # Instantiated fixtures are slow, but give you @david where otherwise you + # would need people(:david). If you don't want to migrate your existing + # test cases which use the @david style and don't mind the speed hit (each + # instantiated fixtures translates to a database query per test method), + # then set this back to true. + self.use_instantiated_fixtures = false + + # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. + # + # Note: You'll currently still have to declare fixtures explicitly in integration tests + # -- they do not yet inherit this setting + fixtures :all + + # Add more helper methods to be used by all tests here... +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/embedded/test/unit/embedded_test.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,54 @@ +# Redmine - project management software +# Copyright (C) 2008 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require File.dirname(__FILE__) + '/../test_helper' + +class EmbeddedTest < ActiveSupport::TestCase + + def setup + Setting.plugin_embedded = { 'path' => '/path/to', + 'index' => 'main.html overview-summary.html index.html', + 'extensions' => 'html png gif', + 'template' => 'doxygen', + 'encoding' => '', + 'menu' => 'Embedded' } + end + + def test_available_templates + assert_equal ['doxygen', 'javadoc', 'rcov'], Redmine::Plugins::Embedded.available_templates + end + + def test_assets + assert_equal ['rcov.css', 'rcov.js'], Redmine::Plugins::Embedded.assets('rcov') + end + + def test_detect_template_from_path + to_test = { '/path/to/doc' => 'doxygen', + '/path/to/javadoc/html' => 'javadoc' } + + to_test.each { |path, template| assert_equal template, Redmine::Plugins::Embedded.detect_template_from_path(path) } + end + + def test_valid_extension + to_test = {'index.html' => true, + 'path/to/index.html' => true, + 'path/to/image.png' => true, + 'path/to/something.else' => false} + + to_test.each { |path, expected| assert_equal expected, Redmine::Plugins::Embedded.valid_extension?(path) } + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/engines/tasks/.svn/entries Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,62 @@ +10 + +dir +4993 +http://redmine.rubyforge.org/svn/trunk/vendor/plugins/engines/tasks +http://redmine.rubyforge.org/svn + + + +2009-12-18T14:41:37.649419Z +3186 +jplang + + + + + + + + + + + + + + +e93f8b46-1217-0410-a6f0-8f06a7374b81 + +engines.rake +file + + + + +2011-03-03T11:05:12.000000Z +10b9e5aacd9d0673e694f6ababd6ee3b +2009-12-18T14:41:37.649419Z +3186 +jplang + + + + + + + + + + + + + + + + + + + + + +10953 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/open_id_authentication/tasks/.svn/entries Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,62 @@ +10 + +dir +4993 +http://redmine.rubyforge.org/svn/trunk/vendor/plugins/open_id_authentication/tasks +http://redmine.rubyforge.org/svn + + + +2009-02-11T19:06:45.087605Z +2438 +edavis10 + + + + + + + + + + + + + + +e93f8b46-1217-0410-a6f0-8f06a7374b81 + +open_id_authentication_tasks.rake +file + + + + +2011-03-03T11:05:12.000000Z +54b595ee92e0adb364a9086340b2af51 +2009-02-11T19:06:45.087605Z +2438 +edavis10 + + + + + + + + + + + + + + + + + + + + + +1041 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/README.rdoc Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,43 @@ += Redmine Checkout plugin + +Author:: Holger Just +URL:: http://dev.holgerjust.de/projects/redmine-checkout + +This plugin to Redmine adds a link to the actual repository to the GUI. + +This plugin includes ZeroClipboard[http://code.google.com/p/zeroclipboard/] +by Joseph Huckaby. This software is licensed under the +{GNU Lesser General Public License}[http://www.gnu.org/licenses/lgpl.html]. + +Copyright (c) 2009, 2010 Holger Just + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + += Installation + +The installation follows the standard installation path from +http://www.redmine.org/projects/redmine/wiki/Plugins + +1. Copy the software to the vendor/plugins directory. Make sure that the name + of the directory is redmine_checkout. +2. Run rake db:migrate_plugins RAILS_ENV=production +3. Restart Redmine
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/Rakefile Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,10 @@ +#!/usr/bin/env ruby +require 'redmine_plugin_support' + +Dir[File.expand_path(File.dirname(__FILE__)) + "/lib/tasks/**/*.rake"].sort.each { |ext| load ext } + +RedminePluginSupport::Base.setup do |plugin| + plugin.project_name = 'redmine_checkout' + plugin.default_task = [:spec] + plugin.tasks = [:doc, :release, :clean, :spec, :stats] +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/projects/settings/_repository_checkout.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,54 @@ +<p><%= form.select(:checkout_overwrite, [ + [l(:general_text_Yes), "1"], + [l(:general_text_No), "0"] + ], + {}, + :onchange => <<-EOF + Effect.toggle($('checkout_settings'), 'slide', {duration:0.2}); + EOF + )%></p> + +<div id="checkout_settings" <%= 'style="display:none;"' unless form.object.checkout_overwrite? %>><fieldset> + <legend><%=l :label_checkout %></legend> + + <p><%= form.text_area :checkout_description, :cols => 60, :rows => 5, :class => 'wiki-edit', :label => :field_description %></p> + <%= wikitoolbar_for 'repository_checkout_description' %> + + <% if form.object.scm_name == 'Subversion' %> + <p><%= form.select :checkout_display_login,[ + [l(:label_display_login_none), ''], + [l(:label_display_login_username), 'username'], + [l(:label_display_login_password), 'password'] + ], + :label => :setting_checkout_display_login %></p> + <% end %> + + <p><%= form.check_box :checkout_display_command %></p> + + <% javascript_tag do %> + protocolForm = new Subform( + '<%= escape_javascript(render(:partial => "projects/settings/repository_checkout_protocol", :locals => {:protocol => Checkout::Protocol.new({:protocol => form.object.scm_name, :append_path => form.object.allow_subtree_checkout? ? 1: 0, :repository => form.object})})) %>', + <%= form.object.checkout_protocols.length %>, + 'checkout_protocol_table' + ); + <% end %> + <p><label><%=l :label_protocol_plural %></label><%=l :help_repository_checkout_protocols %></p> + <%= hidden_field_tag 'repository[checkout_protocols][-1][protocol]', 'empty' %> + <table class="list checkout_protocol_table"> + <thead><tr> + <th class="protocol_protocol" ><%= l(:setting_protocol)%></th> + <th class="protocol_command" ><%= l(:setting_checkout_command)%></th> + <th class="protocol_fixed_url" ><%= l(:setting_checkout_fixed_url) %></th> + <th class="protocol_access" ><%= l(:label_permissions) %></th> + <th class="protocol_append_path"><%= l(:label_append_path) %></th> + <th class="protocol_is_default" ><%= l(:label_default) %></th> + <th class="protocol_delete" ></th> + </tr></thead> + <tbody id="checkout_protocol_table"> + <% form.object.checkout_protocols.each_with_index do |protocol, index| %> + <%= render :partial => 'projects/settings/repository_checkout_protocol', :locals => {:protocol => protocol, :index => index, :classes => cycle('odd', 'even')} %> + <% end %> + </tbody> + </table> + <div style="text-align: right"><%= link_to_function l(:button_add_protocol), "protocolForm.add()", {:class => "icon icon-add"} %></div> +</fieldset></div>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/projects/settings/_repository_checkout_protocol.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,18 @@ +<% + index ||= "--INDEX--" + classes ||= "" + + protocol = Checkout::Protocol.new(protocol) unless protocol.is_a? Checkout::Protocol +%> +<tr id="<%= "checkout_protocols_#{index}" %>" class="<%= classes %>" <%= 'style="display:none"' if index == '--INDEX--' %>> + <td class="protocol_protocol"><%= text_field_tag "repository[checkout_protocols][#{index}][protocol]", protocol.protocol, :size => 10 %></td> + <td class="protocol_command"><%= text_field_tag "repository[checkout_protocols][#{index}][command]", protocol.command, :size => 15 %></td> + <td class="protocol_fixed_url"><%= text_field_tag "repository[checkout_protocols][#{index}][fixed_url]", protocol.fixed_url, :size => 60 %></td> + <td class="protocol_access"><%= select_tag "repository[checkout_protocols][#{index}][access]", options_for_select([ + [l(:label_access_read_write), 'read+write'], + [l(:label_access_read_only), 'read-only'], + [l(:label_access_permission), 'permission']], protocol.access) %></td> + <td class="protocol_append_path"><%= check_box_tag "repository[checkout_protocols][#{index}][append_path]", 1, protocol.append_path? %></td> + <td class="protocol_is_default"><%= check_box_tag "repository[checkout_protocols][#{index}][is_default]", 1, protocol.default? %></td> + <td class="protocol_delete"><%= image_to_function 'delete.png', "var e=$('checkout_protocols_#{index}');var parent=e.up(\"tbody\");e.remove();recalculate_even_odd(parent);return false" %></td> +</tr>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/redmine_checkout_hooks/_view_repositories_show_contextual.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,36 @@ +<div class="repository-info"> + <% if repository.checkout_description.present? %> + <div class="wiki<%= ' bottomline' if protocols.present? %>"><%= textilizable repository.checkout_description %></div> + <% end %> + <% if protocols.present? %> + <div id="checkout_box"> + <ul id="checkout_protocols"> + <% protocols.each do |p| -%> + <li> + <a <%= 'class="selected"' if p == default_protocol %> id="checkout_protocol_<%= p.protocol.to_s.underscore %>" data-permission="<%= p.access_rw(User.current) %>" href="<%= URI.escape p.url(checkout_path) %>"><%=h p.protocol %></a> + </li> + <% end -%> + </ul> + <%= text_field_tag :checkout_url, h(default_protocol.full_command(checkout_path)), :readonly => true %> + <%- if Setting.checkout_use_zero_clipboard? %> + <div id="clipboard_container" title="<%= l(:label_copy_to_clipboard) %>" style="display: none;"> + <div id="clipboard_button"><%= image_tag 'paste.png', :plugin => 'redmine_checkout' %></div> + </div> + <% end -%> + <% if default_protocol %><p><%=l :label_access_type, :type => l(default_protocol.access_label(User.current)) %></p><% end %> + + <% javascript_tag do %> + var checkout_access = $H({<%= protocols.inject([]){|r,p| r << "'checkout_protocol_#{p.protocol.to_s.underscore}': '#{l(p.access_label(User.current))}'"}.join(', ') %>}); + var checkout_commands = $H({<%= protocols.inject([]){|r,p| r << "'checkout_protocol_#{p.protocol.to_s.underscore}': '#{escape_javascript(p.full_command(checkout_path))}'"}.join(', ') %>}); + <%- if Setting.checkout_use_zero_clipboard? %>ZeroClipboard.setMoviePath( '<%= image_path('ZeroClipboard.swf', :plugin => 'redmine_checkout') %>' );<% end %> + <% end %> + </div> + <% end%> +</div> +<div style="clear: left"></div> + +<% content_for :header_tags do %> + <%= stylesheet_link_tag 'checkout', :plugin => 'redmine_checkout' %> + <%= javascript_include_tag 'checkout', :plugin => 'redmine_checkout' %> + <%= (javascript_include_tag 'ZeroClipboard', :plugin => 'redmine_checkout') if Setting.checkout_use_zero_clipboard? %> +<% end %> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/settings/_checkout.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,43 @@ +<% form_tag({:action => 'edit', :tab => 'checkout'}) do %> + +<% javascript_tag do %> +protocolForms = $H(); + +document.observe("dom:loaded", function() { + $('tab-content-checkout').select('fieldset.collapsed').each(function(e){ + e.down('div').hide(); + }); + <% + CheckoutHelper.supported_scm.select{|scm| Setting.enabled_scm.include?(scm)}.each do |scm| + next if Setting.send("checkout_overwrite_description_#{scm}?") + -%> + $('settings_checkout_description_<%= scm %>').up('div').up('div').hide(); + <%- end %> +}); +<% end %> + + +<div class="box tabular settings"> +<p><%= setting_check_box :checkout_display_checkout_info %></p> + +<p><%= setting_text_area :checkout_description_Abstract, :cols => 60, :rows => 5, :class => 'wiki-edit', :label => :field_description %></p> +<%= wikitoolbar_for 'settings_checkout_description_Abstract' %> + +<p><%= setting_check_box :checkout_use_zero_clipboard %></p> + +<% CheckoutHelper.supported_scm.select{|scm| Setting.enabled_scm.include?(scm)}.each do |scm| -%> +<fieldset class="collapsible collapsed"> + <legend onclick="toggleFieldset(this);"><%= "Repository::#{scm}".constantize.scm_name %></legend> + <div><%= render :partial => 'checkout_scm', :locals => {:scm => scm} %></div> +</fieldset> +<%- end %> + +</div> + +<%= submit_tag l(:button_save) %> +<%- end %> + +<% content_for :header_tags do %> + <%= javascript_include_tag 'subform', :plugin => 'redmine_checkout' %> + <%= stylesheet_link_tag 'checkout', :plugin => 'redmine_checkout' %> +<% end %>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/settings/_checkout_protocol.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,19 @@ +<% + index ||= "--INDEX--" + classes ||= "" + + protocol = Checkout::Protocol.new(protocol) unless protocol.is_a? Checkout::Protocol +%> +<tr id="<%= "checkout_protocols_#{scm}_#{index}" %>" class="<%= classes %>" <%= 'style="display:none"' if index == '--INDEX--' %>> + <td class="protocol_protocol" ><%= text_field_tag "settings[checkout_protocols_#{scm}][#{index}][protocol]", protocol.protocol, :size => 10 %></td> + <td class="protocol_command" ><%= text_field_tag "settings[checkout_protocols_#{scm}][#{index}][command]", protocol.command, :size => 15 %></td> + <td class="protocol_regex" ><%= text_field_tag "settings[checkout_protocols_#{scm}][#{index}][regex]", protocol.regex, :size => 30 %></td> + <td class="protocol_regex_replacement"><%= text_field_tag "settings[checkout_protocols_#{scm}][#{index}][regex_replacement]", protocol.regex_replacement, :size => 30 %></td> + <td class="protocol_access" ><%= select_tag "settings[checkout_protocols_#{scm}][#{index}][access]", options_for_select([ + [l(:label_access_read_write), 'read+write'], + [l(:label_access_read_only), 'read-only'], + [l(:label_access_permission), 'permission']], protocol.access) %></td> + <td class="protocol_append_path"><%= check_box_tag "settings[checkout_protocols_#{scm}][#{index}][append_path]", 1, protocol.append_path? %></td> + <td class="protocol_is_default"><%= check_box_tag "settings[checkout_protocols_#{scm}][#{index}][is_default]", 1, protocol.default? %></td> + <td class="protocol_delete"><%= image_to_function 'delete.png', "var e=$('checkout_protocols_#{scm}_#{index}');var parent=e.up(\"tbody\");e.remove();recalculate_even_odd(parent);return false" %></td> +</tr>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/settings/_checkout_scm.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,46 @@ +<div> + <p><%= setting_check_box "checkout_overwrite_description_#{scm}", :label => :setting_checkout_overwrite_description, :onclick => <<-EOF + Effect.toggle($('settings_checkout_description_#{scm}').up("div").up("div"), 'slide', {duration:0.2}); + EOF + %></p> + + <div> + <p><%= setting_text_area "checkout_description_#{scm}", :cols => 60, :rows => 5, :class => 'wiki-edit', :label => :field_description %></p> + <%= wikitoolbar_for "settings_checkout_description_#{scm}" %> + </div> + + <% if scm == 'Subversion' %> + <p><%= setting_select "checkout_display_login",[ + [l(:label_display_login_username), 'username'], + [l(:label_display_login_password), 'password'] + ], + :blank => :label_display_login_none %></p> + <% end %> + + <p><%= setting_check_box "checkout_display_command_#{scm}", :label => :field_checkout_display_command %></p> + + <% javascript_tag do %> + <% repo = "Repository::#{scm}".constantize %> + var subform = new Subform('<%= escape_javascript(render(:partial => "checkout_protocol", :locals => {:protocol => Checkout::Protocol.new({:protocol => repo.scm_name, :append_path => (repo.allow_subtree_checkout? ? '1' : '0'), :command => repo.checkout_default_command}), :scm => scm})) %>',<%= Setting.send("checkout_protocols_#{scm}").length %>,'settings_checkout_protocols_<%= scm %>'); + protocolForms.set('<%= scm %>', subform); + <% end %> + <p><label><%=l :label_protocol_plural %></label><%=l :help_checkout_protocols %></p> + <table class="list checkout_protocol_table"> + <thead><tr> + <th class="protocol_protocol" ><%= l(:setting_protocol)%></th> + <th class="protocol_command" ><%= l(:setting_checkout_command)%></th> + <th class="protocol_regex" ><%= l(:setting_checkout_url_regex) %></th> + <th class="protocol_regex_replacement"><%= l(:setting_checkout_url_regex_replacement) %></th> + <th class="protocol_access" ><%= l(:label_permissions) %></th> + <th class="protocol_append_path" ><%= l(:label_append_path) %></th> + <th class="protocol_is_default" ><%= l(:label_default) %></th> + <th class="protocol_delete" ></th> + </tr></thead> + <tbody id="settings_checkout_protocols_<%= scm %>"> + <% Setting.send("checkout_protocols_#{scm}").each_with_index do |protocol, index| %> + <%= render :partial => 'checkout_protocol', :locals => {:protocol => Checkout::Protocol.new(protocol), :scm => scm, :index => index, :classes => cycle('odd', 'even')} %> + <% end %> + </tbody> + </table> + <div style="text-align: right"><%= link_to_function l(:button_add_protocol), "protocolForms.get('#{scm}').add()", {:class => "icon icon-add"} %></div> +</div>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/app/views/settings/_redmine_checkout.rhtml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,1 @@ +<%=l(:help_moved_settings, :link => link_to(l(:label_settings_location), {:controller => 'settings', :action => 'index', :tab => 'checkout'})) %>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/images/ZeroClipboard.as Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,81 @@ +package { + // Simple Set Clipboard System + // Author: Joseph Huckaby + + import flash.display.Stage; + import flash.display.Sprite; + import flash.display.LoaderInfo; + import flash.display.StageScaleMode; + import flash.events.*; + import flash.display.StageAlign; + import flash.display.StageScaleMode; + import flash.external.ExternalInterface; + import flash.system.Security; + import flash.utils.*; + import flash.system.System; + + public class ZeroClipboard extends Sprite { + + private var id:String = ''; + private var button:Sprite; + private var clipText:String = ''; + + public function ZeroClipboard() { + // constructor, setup event listeners and external interfaces + stage.scaleMode = StageScaleMode.EXACT_FIT; + flash.system.Security.allowDomain("*"); + + // import flashvars + var flashvars:Object = LoaderInfo( this.root.loaderInfo ).parameters; + id = flashvars.id; + + // invisible button covers entire stage + button = new Sprite(); + button.buttonMode = true; + button.useHandCursor = true; + button.graphics.beginFill(0xCCFF00); + button.graphics.drawRect(0, 0, Math.floor(flashvars.width), Math.floor(flashvars.height)); + button.alpha = 0.0; + addChild(button); + button.addEventListener(MouseEvent.CLICK, clickHandler); + + button.addEventListener(MouseEvent.MOUSE_OVER, function(event:Event) { + ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseOver', null ); + } ); + button.addEventListener(MouseEvent.MOUSE_OUT, function(event:Event) { + ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseOut', null ); + } ); + button.addEventListener(MouseEvent.MOUSE_DOWN, function(event:Event) { + ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseDown', null ); + } ); + button.addEventListener(MouseEvent.MOUSE_UP, function(event:Event) { + ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'mouseUp', null ); + } ); + + // external functions + ExternalInterface.addCallback("setHandCursor", setHandCursor); + ExternalInterface.addCallback("setText", setText); + + // signal to the browser that we are ready + ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'load', null ); + } + + public function setText(newText) { + // set the maximum number of files allowed + clipText = newText; + } + + public function setHandCursor(enabled:Boolean) { + // control whether the hand cursor is shown on rollover (true) + // or the default arrow cursor (false) + button.useHandCursor = enabled; + } + + private function clickHandler(event:Event):void { + // user click copies text to clipboard + // as of flash player 10, this MUST happen from an in-movie flash click event + System.setClipboard( clipText ); + ExternalInterface.call( 'ZeroClipboard.dispatch', id, 'complete', clipText ); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/images/button.svg Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,11 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"> + <defs> + <linearGradient id="gradient" x1="100%" y1="100%"> + <stop offset="0%" style="stop-color:#ddd; stop-opacity:1" /> + <stop offset="100%" style="stop-color:#f8f8f8; stop-opacity:1" /> + </linearGradient> + </defs> + <rect width="100%" height="100%" style="fill:url(#gradient)"/> +</svg> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/images/button_focus.svg Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,11 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"> + <defs> + <linearGradient id="gradient" x1="100%" y1="100%"> + <stop offset="0%" style="stop-color:#507AAA; stop-opacity:1" /> + <stop offset="100%" style="stop-color:#759fcf; stop-opacity:1" /> + </linearGradient> + </defs> + <rect width="100%" height="100%" style="fill:url(#gradient)"/> +</svg> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/images/button_selected.svg Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,11 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"> + <defs> + <linearGradient id="gradient" x1="100%" y1="100%"> + <stop offset="0%" style="stop-color:#aaa; stop-opacity:1" /> + <stop offset="100%" style="stop-color:#ccc; stop-opacity:1" /> + </linearGradient> + </defs> + <rect width="100%" height="100%" style="fill:url(#gradient)"/> +</svg> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/javascripts/ZeroClipboard.js Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,311 @@ +// Simple Set Clipboard System +// Author: Joseph Huckaby + +var ZeroClipboard = { + + version: "1.0.7", + clients: {}, // registered upload clients on page, indexed by id + moviePath: 'ZeroClipboard.swf', // URL to movie + nextId: 1, // ID of next movie + + $: function(thingy) { + // simple DOM lookup utility function + if (typeof(thingy) == 'string') thingy = document.getElementById(thingy); + if (!thingy.addClass) { + // extend element with a few useful methods + thingy.hide = function() { this.style.display = 'none'; }; + thingy.show = function() { this.style.display = ''; }; + thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; }; + thingy.removeClass = function(name) { + var classes = this.className.split(/\s+/); + var idx = -1; + for (var k = 0; k < classes.length; k++) { + if (classes[k] == name) { idx = k; k = classes.length; } + } + if (idx > -1) { + classes.splice( idx, 1 ); + this.className = classes.join(' '); + } + return this; + }; + thingy.hasClass = function(name) { + return !!this.className.match( new RegExp("\\s*" + name + "\\s*") ); + }; + } + return thingy; + }, + + setMoviePath: function(path) { + // set path to ZeroClipboard.swf + this.moviePath = path; + }, + + dispatch: function(id, eventName, args) { + // receive event from flash movie, send to client + var client = this.clients[id]; + if (client) { + client.receiveEvent(eventName, args); + } + }, + + register: function(id, client) { + // register new client to receive events + this.clients[id] = client; + }, + + getDOMObjectPosition: function(obj, stopObj) { + // get absolute coordinates for dom element + var info = { + left: 0, + top: 0, + width: obj.width ? obj.width : obj.offsetWidth, + height: obj.height ? obj.height : obj.offsetHeight + }; + + while (obj && (obj != stopObj)) { + info.left += obj.offsetLeft; + info.top += obj.offsetTop; + obj = obj.offsetParent; + } + + return info; + }, + + Client: function(elem) { + // constructor for new simple upload client + this.handlers = {}; + + // unique ID + this.id = ZeroClipboard.nextId++; + this.movieId = 'ZeroClipboardMovie_' + this.id; + + // register client with singleton to receive flash events + ZeroClipboard.register(this.id, this); + + // create movie + if (elem) this.glue(elem); + } +}; + +ZeroClipboard.Client.prototype = { + + id: 0, // unique ID for us + ready: false, // whether movie is ready to receive events or not + movie: null, // reference to movie object + clipText: '', // text to copy to clipboard + handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor + cssEffects: true, // enable CSS mouse effects on dom container + handlers: null, // user event handlers + + glue: function(elem, appendElem, stylesToAdd) { + // glue to DOM element + // elem can be ID or actual DOM element object + this.domElement = ZeroClipboard.$(elem); + + // float just above object, or zIndex 99 if dom element isn't set + var zIndex = 99; + if (this.domElement.style.zIndex) { + zIndex = parseInt(this.domElement.style.zIndex, 10) + 1; + } + + if (typeof(appendElem) == 'string') { + appendElem = ZeroClipboard.$(appendElem); + } + else if (typeof(appendElem) == 'undefined') { + appendElem = document.getElementsByTagName('body')[0]; + } + + // find X/Y position of domElement + var box = ZeroClipboard.getDOMObjectPosition(this.domElement, appendElem); + + // create floating DIV above element + this.div = document.createElement('div'); + var style = this.div.style; + style.position = 'absolute'; + style.left = '' + box.left + 'px'; + style.top = '' + box.top + 'px'; + style.width = '' + box.width + 'px'; + style.height = '' + box.height + 'px'; + style.zIndex = zIndex; + + if (typeof(stylesToAdd) == 'object') { + for (addedStyle in stylesToAdd) { + style[addedStyle] = stylesToAdd[addedStyle]; + } + } + + // style.backgroundColor = '#f00'; // debug + + appendElem.appendChild(this.div); + + this.div.innerHTML = this.getHTML( box.width, box.height ); + }, + + getHTML: function(width, height) { + // return HTML for movie + var html = ''; + var flashvars = 'id=' + this.id + + '&width=' + width + + '&height=' + height; + + if (navigator.userAgent.match(/MSIE/)) { + // IE gets an OBJECT tag + var protocol = location.href.match(/^https/i) ? 'https://' : 'http://'; + html += '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="'+protocol+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="'+width+'" height="'+height+'" id="'+this.movieId+'" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="'+ZeroClipboard.moviePath+'" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="'+flashvars+'"/><param name="wmode" value="transparent"/></object>'; + } + else { + // all other browsers get an EMBED tag + html += '<embed id="'+this.movieId+'" src="'+ZeroClipboard.moviePath+'" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="'+width+'" height="'+height+'" name="'+this.movieId+'" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="'+flashvars+'" wmode="transparent" />'; + } + return html; + }, + + hide: function() { + // temporarily hide floater offscreen + if (this.div) { + this.div.style.left = '-2000px'; + } + }, + + show: function() { + // show ourselves after a call to hide() + this.reposition(); + }, + + destroy: function() { + // destroy control and floater + if (this.domElement && this.div) { + this.hide(); + this.div.innerHTML = ''; + + var body = document.getElementsByTagName('body')[0]; + try { body.removeChild( this.div ); } catch(e) {;} + + this.domElement = null; + this.div = null; + } + }, + + reposition: function(elem) { + // reposition our floating div, optionally to new container + // warning: container CANNOT change size, only position + if (elem) { + this.domElement = ZeroClipboard.$(elem); + if (!this.domElement) this.hide(); + } + + if (this.domElement && this.div) { + var box = ZeroClipboard.getDOMObjectPosition(this.domElement); + var style = this.div.style; + style.left = '' + box.left + 'px'; + style.top = '' + box.top + 'px'; + } + }, + + setText: function(newText) { + // set text to be copied to clipboard + this.clipText = newText; + if (this.ready) this.movie.setText(newText); + }, + + addEventListener: function(eventName, func) { + // add user event listener for event + // event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel + eventName = eventName.toString().toLowerCase().replace(/^on/, ''); + if (!this.handlers[eventName]) this.handlers[eventName] = []; + this.handlers[eventName].push(func); + }, + + setHandCursor: function(enabled) { + // enable hand cursor (true), or default arrow cursor (false) + this.handCursorEnabled = enabled; + if (this.ready) this.movie.setHandCursor(enabled); + }, + + setCSSEffects: function(enabled) { + // enable or disable CSS effects on DOM container + this.cssEffects = !!enabled; + }, + + receiveEvent: function(eventName, args) { + // receive event from flash + eventName = eventName.toString().toLowerCase().replace(/^on/, ''); + + // special behavior for certain events + switch (eventName) { + case 'load': + // movie claims it is ready, but in IE this isn't always the case... + // bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function + this.movie = document.getElementById(this.movieId); + if (!this.movie) { + var self = this; + setTimeout( function() { self.receiveEvent('load', null); }, 1 ); + return; + } + + // firefox on pc needs a "kick" in order to set these in certain cases + if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) { + var self = this; + setTimeout( function() { self.receiveEvent('load', null); }, 100 ); + this.ready = true; + return; + } + + this.ready = true; + this.movie.setText( this.clipText ); + this.movie.setHandCursor( this.handCursorEnabled ); + break; + + case 'mouseover': + if (this.domElement && this.cssEffects) { + this.domElement.addClass('hover'); + if (this.recoverActive) this.domElement.addClass('active'); + } + break; + + case 'mouseout': + if (this.domElement && this.cssEffects) { + this.recoverActive = false; + if (this.domElement.hasClass('active')) { + this.domElement.removeClass('active'); + this.recoverActive = true; + } + this.domElement.removeClass('hover'); + } + break; + + case 'mousedown': + if (this.domElement && this.cssEffects) { + this.domElement.addClass('active'); + } + break; + + case 'mouseup': + if (this.domElement && this.cssEffects) { + this.domElement.removeClass('active'); + this.recoverActive = false; + } + break; + } // switch eventName + + if (this.handlers[eventName]) { + for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) { + var func = this.handlers[eventName][idx]; + + if (typeof(func) == 'function') { + // actual function reference + func(this, args); + } + else if ((typeof(func) == 'object') && (func.length == 2)) { + // PHP style object + method, i.e. [myObject, 'myMethod'] + func[0][ func[1] ](this, args); + } + else if (typeof(func) == 'string') { + // name of function + window[func](this, args); + } + } // foreach event handler defined + } // user defined handler for event + } + +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/javascripts/checkout.js Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,33 @@ +document.observe("dom:loaded", function() { + /* update the checkout URL if clicked on a protocol */ + $('checkout_protocols').select('a').each(function(e) { + e.observe('click', function(event) { + $('checkout_url').value = checkout_commands.get(this.id); + $('checkout_protocols').select('a').each(function(e) { + e.removeClassName("selected"); + }); + this.addClassName("selected") + + var value = checkout_access.get(this.id); + $('checkout_access').innerHTML = value; + + event.stop(); + }); + }); + /* select the text field contents if activated */ + Event.observe('checkout_url', 'click', function(event) { + this.activate(); + }); + + if (typeof('ZeroClipboard') != 'undefined') { + $('clipboard_container').show(); + clipboard = new ZeroClipboard.Client(); + clipboard.setHandCursor( true ); + clipboard.glue('clipboard_button', 'clipboard_container'); + + clipboard.addEventListener('mouseOver', function (client) { + clipboard.setText( $('checkout_url').value ); + }); + } +}); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/javascripts/subform.js Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,45 @@ +var Subform = Class.create({ + lineIndex: 1, + parentElement: "", + initialize: function(rawHTML, lineIndex, parentElement) { + this.rawHTML = rawHTML; + this.lineIndex = lineIndex; + this.parentElement = parentElement; + }, + + parsedHTML: function() { + return this.rawHTML.replace(/--INDEX--/g, this.lineIndex++); + }, + + add: function() { + var e = $(this.parentElement); + Element.insert(e, { bottom: this.parsedHTML()}); + Effect.toggle(e.childElements().last(), 'slide', {duration:0.2}); + recalculate_even_odd(e); + }, + + add_after: function(e) { + Element.insert(e, { after: this.parsedHTML()}); + Effect.toggle(e.next(), 'slide', {duration:0.2}); + recalculate_even_odd($(this.parentElement)); + }, + + add_on_top: function() { + var e = $(this.parentElement); + Element.insert(e, { top: this.parsedHTML()}); + Effect.toggle(e.childElements().first(), 'slide', {duration:0.2}); + recalculate_even_odd(e); + } +}); + +function recalculate_even_odd(element) { + $A(element.childElements()).inject( + 0, + function(acc, e) + { + e.removeClassName("even"); + e.removeClassName("odd"); + e.addClassName( (acc%2==0) ? "odd" : "even"); return ++acc; + } + ) +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/stylesheets/checkout.css Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,162 @@ +/* Uncomment the following line for nicer tables if you use the alternate theme (or derived). */ +/* @import url(checkout_alternate.css); */ + +table.checkout_protocol_table td { padding-right: 6px; vertical-align: middle; /* Double the border with of text input boxes */ } +table.checkout_protocol_table td.protocol_access { padding-right: 0; } +table.checkout_protocol_table td input[type=text], .checkout_protocol_table td select { width: 100%; } +table.checkout_protocol_table td.protocol_delete { width: 16px; } +table.checkout_protocol_table td.protocol_append_path, table.checkout_protocol_table td.protocol_is_default { text-align: center; } + +.icon-changeset { background-image: url(../../../images/changeset.png);} + +.repository-info { + background-color: #eee; + border: 1px solid #E4E4E4; + padding: 0 10px; + margin: 4px 0 10px; +} + +.bottomline { + border-bottom: 1px solid #ccc; +} + +#checkout_box { + margin: 10px 0; +} + +#checkout_protocols { + height: 23px; + float: left; + margin: 0; + padding: 0; +} + +#checkout_protocols li { + float: left; + list-style-type: none; + margin: 0; + padding: 0; +} + +#checkout_protocols li:first-child a { + border-left-width: 1px; + + /* Standard, Opera 10, IE 9 */ + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + /* Konquerer */ + -khtml-border-top-left-radius: 3px; + -khtml-border-bottom-left-radius: 3px; + /* Gecko (Firefox, ...) */ + -moz-border-radius: 3px 0 0 3px; + /* Webkit (Chrome, Safari, ...) */ + -webkit-border-top-left-radius: 3px; + -webkit-border-bottom-left-radius: 3px; + /* IE <= 9 not supported */ +} + +#checkout_protocols li a, +#clipboard_button { + background-color: #eee; + background: url(../images/button.svg) 0 0 no-repeat; /* Opera needs an "image" :( - using svg for this so it will scale properly without looking too ugly */ + background: -khtml-gradient(linear, left top, left bottom, from(#f8f8f8), to(#ddd)); /* Konquerer */ + background: -moz-linear-gradient(top, #f8f8f8, #ddd); /* Gecko (Firefox, ...) */ + background: -webkit-gradient(linear, left top, left bottom, from(#f8f8f8), to(#ddd)); /* Webkit (Chrome, Safari, ...) */ + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8f8f8', endColorstr='#dddddd'); /* IE 5.5 - 7 */ + -ms-filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8f8f8', endColorstr='#dddddd'); /* IE 8 */ + + border-color: #bbb; + border-style: solid; + border-width: 1px 1px 1px 0; + + color: #333; + display: block; + font-size: 11px; + font-weight: bold; + line-height: 21px; + margin: 0; + padding: 0 10px 0 11px; + text-decoration: none; + text-shadow: 1px 1px 0 #fff; + position: relative; /* to please IE */ +} + +#checkout_protocols li a:hover, +#checkout_protocols li a:focus { + background-color: #507AAA; + background: url(../images/button_focus.svg) 0 0 no-repeat; /* Opera needs an "image" :( - using svg for this so it will scale properly without looking too ugly */ + background: -khtml-gradient(linear, left top, left bottom, from(#759fcf), to(#507AAA)); /* Konquerer */ + background: -moz-linear-gradient(top, #759fcf, #507AAA); /* Gecko (Firefox, ...) */ + background: -webkit-gradient(linear, left top, left bottom, from(#759fcf), to(#507AAA)); /* Webkit (Chrome, Safari, ...) */ + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#759fcf', endColorstr='#507AAA'); /* IE 5.5 - IE 7 */ + -ms-filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#759fcf', endColorstr='#507AAA'); /* IE 8 */ + + color: #fff; + text-shadow: -1px -1px 0 rgba(0,0,0,0.4); + border-top-color: #759fcf; + border-bottom-color: #507AAA; +} + +#checkout_protocols li a.selected, +#clipboard_button.active { + background-color: #bbb; + background: url(../images/button_selected.svg) 0 0 no-repeat; /* Opera needs an "image" :( - using svg for this so it will scale properly without looking too ugly */ + background: -webkit-gradient(linear, left top, left bottom, from(#ccc), to(#aaa)); /* Konquerer */ + background: -moz-linear-gradient(top, #ccc, #aaa); /* Gecko (Firefox, ...) */ + background: -webkit-gradient(linear, left top, left bottom, from(#ccc), to(#aaa)); /* Webkit (Chrome, Safari, ...) */ + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#cccccc', endColorstr='#aaaaaa'); /* IE 5.5 - IE 7 */ + -ms-filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#cccccc', endColorstr='#aaaaaa'); /* IE 8 */ + + color: #000; + text-shadow: 1px 1px 0 rgba(255,255,255,0.4); + border-color: #bbb; +} + +#checkout_url { + border: 1px solid #bbb; + border-width: 1px 1px 1px 0; + background-color: #fff; + color: #000; + font-size: 11px; + height: 16px; + padding: 3px 5px 2px; + width: 400px; + font-family: Monaco,"DejaVu Sans Mono","Bitstream Vera Sans Mono","Courier New",monospace; + margin: 0 5px 0 0; + float: left; +} + +#checkout_box p { + color: #666; + line-height: 23px; + font-size: 11px; + margin: 0 0 0 5px; +} + +span#checkout_access { + font-weight: bold; +} + +#clipboard_container { + position: relative; + float: left; + margin-right: 5px; +} + +#clipboard_button { + height: 21px; + width: 23px; + padding: 0; + border-width: 1px; + text-align: center; + + border-radius: 5px; /* Standard, Opera 10, IE 9 */ + -khtml-border-radius: 3px; /* Konquerer */ + -moz-border-radius: 3px ; /* Gecko (Firefox, ...) */ + -webkit-border-radius: 3px; /* Webkit (Chrome, Safari, ...) */ + /* IE <= 9 not supported */ +} + +#clipboard_button img { + padding-top: 2px; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/assets/stylesheets/checkout_alternate.css Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,2 @@ +table.checkout_protocol_table td { padding-right: 10px !important; /* Double the border with of text input boxes */ } +table.checkout_protocol_table td.protocol_access { padding-right: 2px !important; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/de.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,39 @@ +de: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Checkout-Informationen anzeigen" + setting_checkout_fixed_url: "Checkout-URL" + setting_checkout_url_regex: "Regulärer Ausdruck" + setting_checkout_url_regex_replacement: "Ersatztext" + setting_checkout_display_login: "Mitgliedsnamen anzeigen" + setting_checkout_command: "Checkout-Befehl" + setting_checkout_use_zero_clipboard: "Zwischenablagen-Helfer anzeigen" + + setting_checkout_overwrite_description: "Standard-Beschreibung überschreiben" + field_checkout_overwrite: "Überschreibe Standardeinstellung für Checkout-Protokolle" + field_checkout_display_command: "Checkout-Befehl anzeigen" + + label_protocol_plural: "Protokolle" + button_add_protocol: "Protokoll hinzufügen" + + label_access_type: 'Diese URL erlaubt Zugriff zum <span id="checkout_access">{{type}}</span>.' + label_access_read_only: 'Nur-Lesen' + label_access_read_write: "Lesen+Schreiben" + label_access_permission: "Abhängig von Benutzer-Rechten" + + label_append_path: "Pfad anhängen" + + label_display_login_none: "Mitgliedsnamen nicht anzeigen" + label_display_login_username: "Mitgliedsnamen anzeigen, aber kein Kennwort" + label_display_login_password: "Mitgliedsnamen und Kennwort anzeigen" + + label_copy_to_clipboard: "In die Zwischenablage kopieren" + + help_checkout_protocols: | + Die URLs in Protokollen werden aus der originalen URL erzeugt, auf die der + reguläre Ausdruck und der Ersatztext angewendet werden. Der Ersatztext + erlaubt Rückwärtsreferenzen zu geklammerten Audrücken mit der \1 Notation. + help_repository_checkout_protocols: | + Lassen Sie das Checkout-URL-Feld leer um die URL des Projektarchivs zu verwenden. + help_moved_settings: "Die Konfigurationsseite wurde nach {{link}} verschoben." + label_settings_location: "Administration -> Konfiguration -> Checkout" \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/en-GB.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,39 @@ +en-GB: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "Checkout URL" + setting_checkout_url_regex: "Regular expression" + setting_checkout_url_regex_replacement: "Replacement text" + setting_checkout_display_login: "Display Login" + setting_checkout_command: "Checkout command" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Display checkout command" + + label_protocol_plural: "Protocols" + button_add_protocol: "Add Protocol" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "Do not show login or password" + label_display_login_username: "Show login but no password" + label_display_login_password: "Show login and password" + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/en.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,39 @@ +en: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "Checkout URL" + setting_checkout_url_regex: "Regular expression" + setting_checkout_url_regex_replacement: "Replacement text" + setting_checkout_display_login: "Display Login" + setting_checkout_command: "Checkout command" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Display checkout command" + + label_protocol_plural: "Protocols" + button_add_protocol: "Add Protocol" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "Do not show login or password" + label_display_login_username: "Show login but no password" + label_display_login_password: "Show login and password" + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/es.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,39 @@ +es: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "URL de checkout" + setting_checkout_url_regex: "Expresion regular" + setting_checkout_url_regex_replacement: "Texto de remplazo" + setting_checkout_display_login: "Mostrar usuario" + setting_checkout_command: "Comando de checkout" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Display checkout command" + + label_protocol_plural: "Protocolos" + button_add_protocol: "Crear Protocolo" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "No mostrar usuario o contraseña" + label_display_login_username: "Mostrar usuario pero no contraseña" + label_display_login_password: "Mostrar usuario y contraseña" + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/fr.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,39 @@ +fr: + label_checkout: "Dépôt" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "URL du dépôt" + setting_checkout_url_regex: "Expression Régulière" + setting_checkout_url_regex_replacement: "Texte de substitution" + setting_checkout_display_login: "Affiche le login" + setting_checkout_command: "Checkout command" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Affiche l'URL du dépôt" + + label_protocol_plural: "Protocoles" + button_add_protocol: "Créer un protocole" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "Ne pas afficher le login ni le mot de passe" + label_display_login_username: "Afficher le login, pas le mot de passe" + label_display_login_password: "Afficher le login et le mot de passe" + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/it.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,40 @@ +it: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Visualizza le informazioni sul checkout" + setting_checkout_fixed_url: "URL di checkout" + setting_checkout_url_regex: "Espressione regolare" + setting_checkout_url_regex_replacement: "Testo sostituito" + setting_checkout_display_login: "Login visualizzato" + setting_checkout_command: "Comando per il checkout" + setting_checkout_use_zero_clipboard: "Visualizza l'utility per la copia negli appunti" + + setting_checkout_overwrite_description: "Sovrascrivi la descrizione predefinita" + field_checkout_overwrite: "Sovrascrivi le impostazioni di checkout predefinite" + field_checkout_display_command: "Visualizza il comando per il checkout" + + label_protocol_plural: "Protocolli" + button_add_protocol: "Aggiungi Protocollo" + + label_access_type: 'Questo URL ha accesso <span id="checkout_access">{{type}}</span>.' + label_access_read_only: 'Sola-Lettura' + label_access_read_write: "Lettura+Scrittura" + label_access_permission: "Dipende dai permessi dell'utente" + + label_append_path: "Aggiungi percorso" + + label_display_login_none: "Non mostrare il login e password" + label_display_login_username: "Mostra il login senza password" + label_display_login_password: "Mostra il login e la password" + + label_copy_to_clipboard: "Copia negli appunti" + + help_checkout_protocols: | + Gli URL dei protocolli sono generati applicando le espressioni regolari + ed effettuando la sostituzione dell'URL originale con il testo specificato. + Il testo per la sostituzione può contenere riferimenti a più match usando + la notazione \1 \2... + help_repository_checkout_protocols: | + Lascia il campo URL di checkout bianco per usare l'URL definito nel repository. + help_moved_settings: "La pagina delle impostazioni è stata spostata in {{link}}." + label_settings_location: "Amministrazione -> Impostazioni -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/ja.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,39 @@ +ja: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "チェックアウト URL" + setting_checkout_url_regex: "Regular expression" + setting_checkout_url_regex_replacement: "Replacement text" + setting_checkout_display_login: "ログインの表示" + setting_checkout_command: "Checkout command" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Display checkout command" + + label_protocol_plural: "Protocols" + button_add_protocol: "Add Protocol" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "ログインとパスワードを非表示" + label_display_login_username: "ログインのみ表示" + label_display_login_password: "ログインとパスワードを表示" + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/ko.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,40 @@ +ko: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "체크 아웃 URL" + setting_checkout_url_regex: "정규식" + setting_checkout_url_regex_replacement: "대체 문자열" + setting_checkout_display_login: "로그인 표시" + setting_checkout_command: "Checkout command" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Display checkout command" + + label_protocol_plural: "Protocols" + button_add_protocol: "Add Protocol" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "로그인과 비밀번호를 보여주지 않습니다." + label_display_login_username: "로그인은 보여주지만 비밀번호는 보여주지 않습니다." + label_display_login_password: "로그인과 비밀번호를 보여줍니다." + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout" +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/nl.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,40 @@ +nl: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Checkout-informatie tonen" + setting_checkout_fixed_url: "Checkout-URL" + setting_checkout_url_regex: "Reguliere expressie" + setting_checkout_url_regex_replacement: "Vervangingstekst" + setting_checkout_display_login: "Geef login weer" + setting_checkout_command: "Checkout-opdracht" + setting_checkout_use_zero_clipboard: "Klembord-hulp tonen" + + setting_checkout_overwrite_description: "Standaard omschrijving overschrijven" + field_checkout_overwrite: "Overschrijf standaard instellingen voor checkout-protocollen" + field_checkout_display_command: "Checkout-opdracht tonen" + + label_protocol_plural: "Protocollen" + button_add_protocol: "Protocol toevoegen" + + label_access_type: 'Deze URL heeft <span id="checkout_access">{{type}}</span> toegang.' + label_access_read_only: 'Alleen lezen' + label_access_read_write: "Lezen en schrijven" + label_access_permission: "Afhankelijk van gebruikersrechten" + + label_append_path: "Pad toevoegen" + + label_display_login_none: "Geen logingegevens tonen" + label_display_login_username: "Toon login zonder wachtwoord" + label_display_login_password: "Toon login en wachtwoord" + + label_copy_to_clipboard: "Naar klembord kopiëren" + + help_checkout_protocols: | + De URLs in protocollen worden samengesteld vanuit de originele URL, na + toepassing van de reguliere expressie en vervangingstekst. De vervangingstekst + ondersteunt referenties vanuit tussen haakjes geplaatste expressies + door middel van de \1 notatie. + help_repository_checkout_protocols: | + Laat het veld Checkout-URL leeg om de projectrepository te gebruiken. + help_moved_settings: "De instellingspagina is verplaatst naar {{link}}." + label_settings_location: "Administratie -> Instellingen -> Checkout" \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/pl.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,39 @@ +pl: + label_checkout: "Pobieranie repozytorium" + + setting_checkout_display_checkout_info: "Pokaż informację o możliwości pobrania repozytorium" + setting_checkout_fixed_url: "Adres URL pobierania repozytorium" + setting_checkout_url_regex: "Wyrażenie regularne" + setting_checkout_url_regex_replacement: "Wynikowy adres URL" + setting_checkout_display_login: "Pokaż dane logowania" + setting_checkout_command: "Komenda pobrania repozytorium" + setting_checkout_use_zero_clipboard: "Pokaż pomocnika schowka" + + setting_checkout_overwrite_description: "Nadpisz domyślny opis" + field_checkout_overwrite: "Nadpisz domyślne ustawienia dla protokołów" + field_checkout_display_command: "Pokaż komendę pobrania repozytorium" + + label_protocol_plural: "Protokoły" + button_add_protocol: "Dodaj protokół" + + label_access_type: 'Ten adres URL ma dostęp <span id="checkout_access">{{type}}</span>.' + label_access_read_only: 'Tylko do odczytu' + label_access_read_write: "Odczyt+Zapis" + label_access_permission: "Zależne od uprawnień użytkownika" + + label_append_path: "Dołącz ścieżkę" + + label_display_login_none: "Nie pokazuj loginu ani hasła" + label_display_login_username: "Pokaż tylko login" + label_display_login_password: "Pokaż login i hasło" + + label_copy_to_clipboard: "Kopiuj do schowka" + + help_checkout_protocols: | + Wynikowe adresy URL w protokołach są generowane przez zamianę oryginalnego + adresu URL repozytorium na podstawie wyrażenia regularnego. Wynikowy adres + URL wspiera referencje do grup (tzw. back-references) używając notacji \1. + help_repository_checkout_protocols: | + Pozostaw adres URL pobierania repozytorium pusty aby uzyć adresu zdefiniowanego w ustawieniach projektu. + help_moved_settings: "Ustawienia zostały przeniesione do {{link}}." + label_settings_location: "Administracja -> Ustawienia -> Pobieranie repozytorium"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/config/locales/ro.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,39 @@ +ro: + label_checkout: "Checkout" + + setting_checkout_display_checkout_info: "Display checkout information" + setting_checkout_fixed_url: "URL-ul pentru checkout" + setting_checkout_url_regex: "Expresie regulata (regexp)" + setting_checkout_url_regex_replacement: "Text inlocuitor (regexp)" + setting_checkout_display_login: "Arata datele pentru autentificare" + setting_checkout_command: "Comanda de checkout" + setting_checkout_use_zero_clipboard: "Display clipboard helper" + + setting_checkout_overwrite_description: "Overwrite default description" + field_checkout_overwrite: "Overwrite default settings for checkout protocols" + field_checkout_display_command: "Display checkout command" + + label_protocol_plural: "Protocols" + button_add_protocol: "Add Protocol" + + label_access_type: 'This URL has <span id="checkout_access">{{type}}</span> access.' + label_access_read_only: 'Read-Only' + label_access_read_write: "Read+Write" + label_access_permission: "Depending on user's permissions" + + label_append_path: "Append path" + + label_display_login_none: "Nu afisa username sau parola" + label_display_login_username: "Afiseaza username-ul, dar nu si parola" + label_display_login_password: "Afiseaza atat username-ul, cat si parola" + + label_copy_to_clipboard: "Copy to clipboard" + + help_checkout_protocols: | + The URLs in protocols are generated from applying the regular expression + and the replacement text to the original URL. The replacement text + supports back-references to braced expressions using the \1 notation. + help_repository_checkout_protocols: | + Leave the Checkout URL field empty to use the defined repository URL. + help_moved_settings: "The settings page has been moved to {{link}}." + label_settings_location: "Administration -> Settings -> Checkout"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20091208210439_add_checkout_url_info.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,11 @@ +class AddCheckoutUrlInfo < ActiveRecord::Migration + def self.up + add_column :repositories, :checkout_url_type, :string, :default => 'none', :null => false + add_column :repositories, :checkout_url, :string, :default => '', :null => false + end + + def self.down + remove_column :repository, :checkout_url_type + remove_column :repository, :checkout_url + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20091220173312_add_display_login.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,9 @@ +class AddDisplayLogin < ActiveRecord::Migration + def self.up + add_column :repositories, :display_login, :string, :default => 'none', :null => false + end + + def self.down + remove_column :repositories, :display_login + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100118174556_add_render_link.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,9 @@ +class AddRenderLink < ActiveRecord::Migration + def self.up + add_column :repositories, :render_link, :boolean, :null => true + end + + def self.down + remove_column :repositories, :render_link + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100118235845_remove_defaults.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,14 @@ +class RemoveDefaults < ActiveRecord::Migration + def self.up + change_column :repositories, :checkout_url_type, :string, :default => nil, :null => true + change_column :repositories, :checkout_url, :string, :default => nil, :null => true + change_column :repositories, :display_login, :string, :default => nil, :null => true + end + + def self.down + change_column :repositories, :checkout_url_type, :string, :default => 'none', :null => false + change_column :repositories, :checkout_url, :string, :default => '', :null => false + change_column :repositories, :display_login, :string, :default => 'none', :null => false + end +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100118235909_add_overwrite_option.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,15 @@ +class AddOverwriteOption < ActiveRecord::Migration + def self.up + add_column :repositories, :checkout_url_overwrite, :boolean, :default => false, :null => false + + # existing repositories are set to overwrite the default settings + # This is to keep continuity of settings. + Repository.reset_column_information + Repository.update_all({:checkout_url_overwrite, true}) + end + + def self.down + remove_column :repositories, :checkout_url_overwrite + end +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100203202320_update_settings.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,36 @@ +class UpdateSettings < ActiveRecord::Migration + def self.up + settings = Setting.plugin_redmine_checkout + if settings['checkout_url_type'] == "overwritten" + settings['checkout_url_type'] = "generated" + end + + if settings.has_key? "checkout_url_regex" + settings['checkout_url_regex_default'] = settings.delete("checkout_url_regex") + end + + if settings.has_key? "checkout_url_regex_replacement" + settings['checkout_url_regex_replacement_default'] = settings.delete("checkout_url_regex_replacement") + end + + Setting.plugin_redmine_checkout = settings + end + + def self.down + settings = Setting.plugin_redmine_checkout + if settings['checkout_url_type'] == "generated" + settings['checkout_url_type'] = "overwritten" + end + + if settings.has_key? "checkout_url_regex_default" + settings['checkout_url_regex'] = settings.delete("checkout_url_regex_default") + end + + if settings.has_key? "checkout_url_regex_replacement_default" + settings['checkout_url_regex_replacement'] = settings.delete("checkout_url_regex_replacement_default") + end + + Setting.plugin_redmine_checkout = settings + end +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100426154202_rename_render_link_to_render_type.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,31 @@ +class RenameRenderLinkToRenderType < ActiveRecord::Migration + def self.up + render_link = Setting.plugin_redmine_checkout.delete 'render_link' + unless render_link.nil? + Setting.plugin_redmine_checkout['render_type'] = (render_link == 'true' ? 'link' : 'url') + Setting.plugin_redmine_checkout = Setting.plugin_redmine_checkout + end + + add_column :repositories, :render_type, :string, :default => 'url', :null => false + + Repository.update_all({:render_type => 'link'}, :render_link => true) + Repository.update_all({:render_type => 'url'}, ["render_link != ?", true]) + + remove_column :repositories, :render_link + end + + def self.down + render_type = Setting.plugin_redmine_checkout.delete 'render_type' + unless render_type.nil? + Setting.plugin_redmine_checkout['render_link'] = (render_type == 'link' ? 'true' : 'false') + Setting.plugin_redmine_checkout = Setting.plugin_redmine_checkout + end + + add_column :repositories, :render_link, :boolean, :null => true + + Repository.update_all({:render_link => true}, :render_type => 'link') + Repository.update_all({:render_link => false}, ["render_type != ?", 'link']) + + remove_column :repositories, :render_type + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100512135418_consolidate_repository_options.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,49 @@ +class ConsolidateRepositoryOptions < ActiveRecord::Migration + class Repository < ActiveRecord::Base + def self.inheritance_column + # disable single table inheritance + nil + end + + serialize :checkout_settings, Hash + end + + def self.up + add_column :repositories, :checkout_settings, :text + + Repository.all.each do |r| + r.checkout_settings = { + "checkout_url_type" => r.checkout_url_type, + "checkout_url" => r.checkout_url, + "display_login" => r.display_login, + "render_type" => r.render_type, + "checkout_url_overwrite" => r.checkout_url_overwrite + } + r.save! + end + remove_column :repositories, :checkout_url_type + remove_column :repositories, :checkout_url + remove_column :repositories, :display_login + remove_column :repositories, :render_type + remove_column :repositories, :checkout_url_overwrite + end + + def self.down + add_column :repositories, :checkout_url_type, :string, :default => nil, :null => true + add_column :repositories, :checkout_url, :string, :default => nil, :null => true + add_column :repositories, :display_login, :string, :default => nil, :null => true + add_column :repositories, :render_type, :string, :default => 'url', :null => false + add_column :repositories, :checkout_url_overwrite, :boolean, :default => false, :null => false + + Repository.all.each do |r| + r.checkout_url_type = r.checkout_settings["checkout_url_type"] + r.checkout_url = r.checkout_settings["checkout_url"] + r.display_login = r.checkout_settings["display_login"] + r.render_link = r.checkout_settings["render_link"] + r.checkout_url_overwrite = r.checkout_settings["checkout_url_overwrite"] + r.save! + end + + remove_column :repositories, :checkout_settings + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100609153630_apply_setting_changes.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,113 @@ +class ApplySettingChanges < ActiveRecord::Migration + class Repository < ActiveRecord::Base + def self.inheritance_column + # disable single table inheritance + nil + end + + def scm_name + self.type || 'Abstract' + end + + serialize :checkout_settings, Hash + end + + def self.up + default_commands = { + 'Bazaar' => 'bzr checkout', + 'Cvs' => 'cvs checkout', + 'Darcs' => 'darcs get', + 'Git' => 'git clone', + 'Mercurial' => 'hg clone', + 'Subversion' => 'svn checkout' + } + + ## First migrate the individual repositories + + Repository.all.each do |r| + allow_subtree_checkout = ['Cvs', 'Subversion'].include? r.scm_name + + protocol = case r.checkout_settings['checkout_url_type'] + when 'none', 'generated' + nil + when 'original', 'overwritten' + HashWithIndifferentAccess.new({ "0" => HashWithIndifferentAccess.new({ + :protocol => r.scm_name, + :command => Setting.plugin_redmine_checkout["checkout_cmd_#{r.scm_name}"] || default_commands[r.scm_name], + :regex => "", + :regex_replacement => "", + :fixed_url => (r.checkout_settings['checkout_url_type'] == 'original' ? (r.url || "") : r.checkout_settings["checkout_url"]), + :access => 'permission', + :append_path => (allow_subtree_checkout ? '1' : '0'), + :is_default => '1'}) + }) + end + + r.checkout_settings = Hash.new({ + 'checkout_protocols' => protocol, + 'checkout_description' => "The data contained in this repository can be downloaded to your computer using one of several clients. +Please see the documentation of your version control software client for more information. + +Please select the desired protocol below to get the URL.", + 'checkout_display_login' => (r.checkout_settings['display_login'] == 'none' ? '' : r.checkout_settings['display_login']), + 'checkout_overwrite' => (r.checkout_settings['checkout_url_overwrite'] == 'true') ? '1': '0', + 'checkout_display_command' => (r.checkout_settings["render_type"].to_s == 'cmd') ? '1' : '0' + }) + r.save! + end + + ## Then the global settings + + settings = HashWithIndifferentAccess.new({ + 'display_login' => Setting.plugin_redmine_checkout['display_login'], + 'use_zero_clipboard' => '1', + + 'display_checkout_info' => (Setting.plugin_redmine_checkout['checkout_url_type'] == 'none' ? '0' : '1'), + 'description_Abstract' => <<-EOF +The data contained in this repository can be downloaded to your computer using one of several clients. +Please see the documentation of your version control software client for more information. + +Please select the desired protocol below to get the URL. +EOF + }) + + default_commands.keys.each do |scm| + settings["description_#{scm}"] = '' + settings["overwrite_description_#{scm}"] = '0' + + display_command = (Setting.plugin_redmine_checkout["render_type"].to_s == 'cmd') ? '1' : '0' + settings["display_command_#{scm}"] = display_command + + case Setting.plugin_redmine_checkout['checkout_url_type'] + when 'generated', 'none': + regex = Setting.plugin_redmine_checkout["checkout_url_regex_#{scm}"] + replacement = Setting.plugin_redmine_checkout["checkout_url_regex_replacement_#{scm}"] + when 'original': + regex = '' + replacement = '' + end + + settings["protocols_#{scm}"] = HashWithIndifferentAccess.new({ + # access can be one of + # read+write => this protocol always allows read/write access + # read-only => this protocol always allows read access only + # permission => Access depends on redmine permissions + '0' => HashWithIndifferentAccess.new({ + :protocol => scm, + :command => Setting.plugin_redmine_checkout["checkout_cmd_#{scm}"] || default_commands[scm], + :regex => regex, + :regex_replacement => replacement, + :fixed_url => '', + :access => 'permission', + :append_path => (['Cvs', 'Subversion'].include?(scm) ? '1' : '0'), + :is_default => '1' + }) + }) + end + Setting.plugin_redmine_checkout = settings + end + + def self.down + raise ActiveRecord::IrreversibleMigration.new "Sorry, there is no down migration yet. If you really need one, please create an issue on http://dev.holgerjust.de/projects/redmine-checkout" + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/db/migrate/20100808185600_change_protocol_storage_from_hash_to_array.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,58 @@ +class ChangeProtocolStorageFromHashToArray < ActiveRecord::Migration + class Repository < ActiveRecord::Base + def self.inheritance_column + # disable single table inheritance + nil + end + + def scm_name + self.type || 'Abstract' + end + + serialize :checkout_settings, Hash + end + + def self.up + ## First migrate the individual repositories + Repository.all.each do |r| + next unless r.checkout_settings + next unless r.checkout_settings['checkout_protocols'].is_a? Hash + r.checkout_settings['checkout_protocols'] = r.checkout_settings['checkout_protocols'].sort{|(ak,av),(bk,bv)|ak<=>bk}.collect{|id,protocol| protocol} + r.save! + end + + ## Then the global settings + settings = Setting.plugin_redmine_checkout + settings.keys.grep(/^protocols_/).each do |protocols| + next unless settings[protocols].is_a? Hash + settings[protocols] = settings[protocols].sort{|(ak,av),(bk,bv)|ak<=>bk}.collect{|id,protocol| protocol} + end + Setting.plugin_redmine_checkout = settings + end + + def self.down + ## First migrate the individual repositories + Repository.all.each do |r| + next unless r.checkout_settings['checkout_protocols'].is_a? Hash + r.checkout_settings['checkout_protocols'] = r.checkout_settings['checkout_protocols'].inject(HashWithIndifferentAccess.new) do |result, p| + result[result.length.to_s] = p + end + r.save! + end + + ## Then the global settings + settings = Setting.plugin_redmine_checkout + settings.keys.grep(/^protocols_/).each do |protocols| + next unless r.checkout_settings['checkout_protocols'].is_a? Hash + settings[protocols] = settings[protocols].inject(HashWithIndifferentAccess.new) do |result, p| + result[result.length.to_s] = p + end + end + Setting.plugin_redmine_checkout = settings + + + + + raise ActiveRecord::IrreversibleMigration.new "Sorry, there is no down migration yet. If you really need one, please create an issue on http://dev.holgerjust.de/projects/redmine-checkout" + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/doc/COPYING Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,22 @@ +Copyright (c) 2009 Holger Just + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/init.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,102 @@ +require 'redmine' + +require 'dispatcher' +Dispatcher.to_prepare do + # Patches + require_dependency 'checkout/settings_controller_patch' + + require_dependency 'checkout/repositories_helper_patch' + require_dependency 'checkout/repository_patch' + + require_dependency 'checkout/settings_helper_patch' + require_dependency 'checkout/setting_patch' +end + +# Hooks +require 'checkout/repository_hooks' + +Redmine::Plugin.register :redmine_checkout do + name 'Redmine Checkout plugin' + url 'http://dev.holgerjust.de/projects/redmine-checkout' + author 'Holger Just' + author_url 'http://meine-er.de' + description 'Add links to the actual repository to the repository view.' + version '0.5' + + requires_redmine :version_or_higher => '0.9' + + settings_defaults = HashWithIndifferentAccess.new({ + 'display_login' => nil, + 'use_zero_clipboard' => '1', + + 'display_checkout_info' => '1', + 'description_Abstract' => <<-EOF +The data contained in this repository can be downloaded to your computer using one of several clients. +Please see the documentation of your version control software client for more information. + +Please select the desired protocol below to get the URL. +EOF + }) + + # this is needed for setting the defaults + require 'checkout/repository_patch' + + CheckoutHelper.supported_scm.each do |scm| + klazz = "Repository::#{scm}".constantize + + settings_defaults["description_#{scm}"] = '' + settings_defaults["overwrite_description_#{scm}"] = '0' + settings_defaults["display_command_#{scm}"] = '0' + + # access can be one of + # read+write => this protocol always allows read/write access + # read-only => this protocol always allows read access only + # permission => Access depends on redmine permissions + settings_defaults["protocols_#{scm}"] = [HashWithIndifferentAccess.new({ + :protocol => scm, + :command => klazz.checkout_default_command, + :regex => '', + :regex_replacement => '', + :fixed_url => '', + :access => 'permission', + :append_path => (klazz.allow_subtree_checkout? ? '1' : '0'), + :is_default => '1' + })] + end + + settings :default => settings_defaults, :partial => 'settings/redmine_checkout' + + Redmine::WikiFormatting::Macros.register do + desc <<-EOF +Creates a checkout link to the actual repository. Example: + + use the default checkout protocol !{{repository}} + or use a specific protocol !{{repository(SVN)}} + or use the checkout protocol of a specific specific project: !{{repository(projectname:SVN)}}" +EOF + + macro :repository do |obj, args| + proto = args.first + if proto.to_s =~ %r{^([^\:]+)\:(.*)$} + project_identifier, proto = $1, $2 + project = Project.find_by_identifier(project_identifier) || Project.find_by_name(project_identifier) + else + project = @project + end + + if project && project.repository + protocols = project.repository.checkout_protocols.select{|p| p.access_rw(User.current)} + + if proto.present? + proto_obj = protocols.find{|p| p.protocol.downcase == proto.downcase} + else + proto_obj = protocols.find(&:default?) || protocols.first + end + end + raise "Checkout protocol #{proto} not found" unless proto_obj + + cmd = (project.repository.checkout_display_command? && proto_obj.command.present?) ? proto_obj.command.strip + " " : "" + cmd + link_to(proto_obj.url, proto_obj.url) + end + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/protocol.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,114 @@ +module Checkout + class <<self + def awesome? + # Yes, this plugin is awesome! + true + end + end + + class Protocol + attr_accessor :protocol, :regex, :regex_replacement, :access, :repository + attr_writer :default, :command, :fixed_url, :append_path + + + def initialize(args={}) + args = args.dup + + @protocol = args.delete :protocol + @command = args.delete :command # optional, if not set the default from the repo is used + + # either a fixed url + @fixed_url = args.delete :fixed_url + + # or a regex + @regex = args.delete :regex + @regex_replacement = args.delete :regex_replacement + + @access = args.delete :access + @append_path = args.delete :append_path + @default = args.delete :is_default + + @repository = args.delete :repository + end + + def full_command(path = "") + cmd = "" + if repository.checkout_display_command? + cmd = self.command.present? ? self.command.strip + " " : "" + end + cmd + URI.escape(self.url(path)) + end + + def default? + @default.to_i > 0 + end + + def command + @command || self.repository && self.repository.checkout_default_command || "" + end + + def append_path? + @append_path.to_i > 0 + end + + def access_rw(user) + # reduces the three available access levels 'read+write', 'read-only' and 'permission' + # to 'read+write' and 'read-only' and nil (not allowed) + + @access_rw ||= {} + return @access_rw[user] if @access_rw.key? user + @access_rw[user] = case access + when 'permission' + case + when user.allowed_to?(:commit_access, repository.project) && user.allowed_to?(:browse_repository, repository.project) + 'read+write' + when user.allowed_to?(:browse_repository, repository.project) + 'read-only' + else + nil + end + else + @access + end + end + + def access_label(user) + case access_rw(user) + when 'read+write': :label_access_read_write + when 'read-only': :label_access_read_only + end + end + + def fixed_url + @fixed_url.present? ? @fixed_url : begin + if (regex.blank? || regex_replacement.blank?) + repository.url + else + repository.url.gsub(Regexp.new(regex), regex_replacement) + end + end + rescue RegexpError + repository.url || "" + end + + def url(path = "") + return "" unless repository + + url = fixed_url.sub(/\/+$/, "") + if repository.allow_subtree_checkout? && self.append_path? && path.present? + url = "#{url}/#{path}" + end + + if repository.checkout_display_login? + begin + uri = URI.parse url + (uri.user = repository.login) if repository.login + (uri.password = repository.password) if (repository.checkout_display_login == 'password' && repository.login && repository.password) + url = uri.to_s + rescue URI::InvalidURIError + end + end + url + end + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/repositories_helper_patch.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,34 @@ +require_dependency 'repositories_helper' + +module Checkout + module RepositoriesHelperPatch + def self.included(base) # :nodoc: + base.send(:include, InstanceMethods) + + base.class_eval do + alias_method_chain :repository_field_tags, :checkout + alias_method_chain :scm_select_tag, :javascript + end + end + + module InstanceMethods + def repository_field_tags_with_checkout(form, repository) + tags = repository_field_tags_without_checkout(form, repository) || "" + return tags if repository.class.name == "Repository" + + tags + @controller.send(:render_to_string, :partial => 'projects/settings/repository_checkout', :locals => {:form => form, :repository => repository, :scm => repository.scm_name}) + end + + def scm_select_tag_with_javascript(*args) + content_for :header_tags do + javascript_include_tag('subform', :plugin => 'redmine_checkout') + + stylesheet_link_tag('checkout', :plugin => 'redmine_checkout') + end + scm_select_tag_without_javascript(*args) + end + end + end +end + +RepositoriesHelper.send(:include, Checkout::RepositoriesHelperPatch) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/repository_hooks.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,34 @@ +module Checkout + class RepositoryHooks < Redmine::Hook::ViewListener + # Renders the checkout URL + # + # Context: + # * :project => Current project + # * :repository => Current Repository + # + def view_repositories_show_contextual(context={}) + if context[:repository].present? && Setting.checkout_display_checkout_info? + protocols = context[:repository].checkout_protocols.select do |p| + p.access_rw(User.current) + end + + path = context[:controller].instance_variable_get("@path") + if path && context[:controller].instance_variable_get("@entry") + # a single file is showing, so we return only the directory + path = File.dirname(path) + end + + default = protocols.find(&:default?) || protocols.first + + context.merge!({ + :protocols => protocols, + :default_protocol => default, + :checkout_path => path + }) + + options = {:partial => "redmine_checkout_hooks/view_repositories_show_contextual"} + context[:controller].send(:render_to_string, {:locals => context}.merge(options)) + end + end + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/repository_patch.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,186 @@ +require_dependency 'repository' +require_dependency 'checkout_helper' + +module Checkout + module RepositoryPatch + def self.included(base) # :nodoc: + base.extend(ClassMethods) + base.send(:include, InstanceMethods) + + base.class_eval do + unloadable + serialize :checkout_settings, Hash + end + end + + module ClassMethods + def allow_subtree_checkout? + # default implementation + false + end + + def checkout_default_command + # default implementation + "" + end + end + + module InstanceMethods + def after_initialize + self.checkout_settings ||= {} + end + + def checkout_overwrite=(value) + checkout_settings['checkout_overwrite'] = value + end + + def checkout_overwrite + (checkout_settings['checkout_overwrite'].to_i > 0) ? '1' : '0' + end + + def checkout_overwrite? + self.scm_name != 'Abstract' && checkout_overwrite.to_i > 0 + end + + def checkout_description=(value) + checkout_settings['checkout_description'] = value + end + + def checkout_description + if checkout_overwrite? + checkout_settings['checkout_description'] + else + if CheckoutHelper.supported_scm.include?(scm_name) && Setting.send("checkout_overwrite_description_#{scm_name}?") + Setting.send("checkout_description_#{scm_name}") + else + Setting.send("checkout_description_Abstract") + end + end + end + + def checkout_protocols + @checkout_protocols ||= begin + if CheckoutHelper.supported_scm.include? scm_name + if checkout_overwrite? + protocols = checkout_settings['checkout_protocols'] || [] + else + protocols = Setting.send("checkout_protocols_#{scm_name}") || [] + end + else + protocols = [] + end + + protocols.collect do |p| + Checkout::Protocol.new p.merge({:repository => self}) + end + end + end + + def checkout_protocols=(value) + # value is an Array or a Hash + if value.is_a? Hash + value = value.dup.delete_if {|id, protocol| id.to_i < 0 } + value = value.sort{|(ak,av),(bk,bv)|ak<=>bk}.collect{|id,protocol| protocol} + end + + checkout_settings['checkout_protocols'] = value + end + + def checkout_display_login + if checkout_overwrite? && self.scm_name == "Subversion" + result = checkout_settings['checkout_display_login'] + else + result = Setting.checkout_display_login + end + (result.to_i > 0) ? '1' : '0' + end + + def checkout_display_login? + checkout_display_login.to_i > 0 + end + + def checkout_display_login=(value) + value = nil unless self.scm_name == "Subversion" + checkout_settings['checkout_display_login'] = value + end + + def checkout_display_command? + checkout_display_command.to_i > 0 + end + + def checkout_display_command=(value) + checkout_settings['checkout_display_command'] = value + end + + def checkout_display_command + if checkout_overwrite? + checkout_settings['checkout_display_command'] + else + Setting.send("checkout_display_command_#{scm_name}") + end + end + + def allow_subtree_checkout? + self.class.allow_subtree_checkout? + end + + def checkout_default_command + self.class.checkout_default_command + end + end + end +end + +Repository.send(:include, Checkout::RepositoryPatch) + +subtree_checkout_repos = ["Subversion", "Cvs"] +commands = { + 'Bazaar' => 'bzr checkout', + 'Cvs' => 'cvs checkout', + 'Darcs' => 'darcs get', + 'Git' => 'git clone', + 'Mercurial' => 'hg clone', + 'Subversion' => 'svn checkout' +} + +CheckoutHelper.supported_scm.each do |scm| + require_dependency "repository/#{scm.underscore}" + cls = Repository.const_get(scm) + + allow_subtree_checkout = "" + if subtree_checkout_repos.include? scm + allow_subtree_checkout = <<-EOS + def allow_subtree_checkout? + true + end + EOS + end + + checkout_command = "" + if commands[scm] + checkout_command = <<-EOS + def checkout_default_command + '#{commands[scm]}' + end + EOS + end + + class_mod = Module.new + class_mod.module_eval(<<-EOF + def self.included(base) + base.extend ChildClassMethods + + base.class_eval do + unloadable + serialize :checkout_settings, Hash + end + end + + module ChildClassMethods + #{allow_subtree_checkout} + #{checkout_command} + end + EOF + ) + cls.send(:include, class_mod) +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/setting_patch.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,75 @@ +require_dependency 'setting' + +module Checkout + module SettingPatch + def self.included(base) # :nodoc: + base.extend(ClassMethods) + + base.class_eval do + unloadable + + # Defines getter and setter for each setting + # Then setting values can be read using: Setting.some_setting_name + # or set using Setting.some_setting_name = "some value" + Redmine::Plugin.find(:redmine_checkout).settings[:default].keys.each do |name| + if name.start_with?('protocols_') + default = "[]" + else + default = <<-END_SRC + begin + default = Setting.available_settings['plugin_redmine_checkout']['default']['#{name}'] + # perform a deep copy of the default + Marshal::load(Marshal::dump(default)) + end + END_SRC + end + + src = <<-END_SRC + def self.checkout_#{name} + self.plugin_redmine_checkout[:#{name}] || #{default} + end + + def self.checkout_#{name}? + self.checkout_#{name}.to_i > 0 + end + + def self.checkout_#{name}=(value) + setting = Setting.plugin_redmine_checkout + setting[:#{name}] = value + Setting.plugin_redmine_checkout = setting + end + END_SRC + class_eval src, __FILE__, __LINE__ + end + + class <<self + alias_method :store_without_checkout, :[]= + alias_method :[]=, :store_with_checkout + + alias_method :retrieve_without_checkout, :[] + alias_method :[], :retrieve_with_checkout + end + end + end + + module ClassMethods + def store_with_checkout(name, value) + if name.to_s.starts_with? "checkout_" + self.send("#{name}=", value) + else + store_without_checkout(name, value) + end + end + + def retrieve_with_checkout(name) + if name.to_s.starts_with? "checkout_" + self.send("#{name}") + else + retrieve_without_checkout(name) + end + end + end + end +end + +Setting.send(:include, Checkout::SettingPatch) \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/settings_controller_patch.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,44 @@ +require_dependency 'settings_controller' + +module Checkout + module SettingsControllerPatch + def self.included(base) # :nodoc: + base.send(:include, InstanceMethods) + + base.class_eval do + unloadable + + alias_method_chain :edit, :checkout + end + end + + module InstanceMethods + def edit_with_checkout + if request.post? && params['tab'] == 'checkout' + if params[:settings] && params[:settings].is_a?(Hash) + settings = HashWithIndifferentAccess.new + (params[:settings] || {}).each do |name, value| + if name = name.to_s.slice(/checkout_(.+)/, 1) + case value + when Array + # remove blank values in array settings + value.delete_if {|v| v.blank? } + when Hash + # change protocols hash to array. + value = value.sort{|(ak,av),(bk,bv)|ak<=>bk}.collect{|id,protocol| protocol} if name.start_with? "protocols_" + end + settings[name.to_sym] = value + end + end + + Setting.plugin_redmine_checkout = settings + params[:settings] = {} + end + end + edit_without_checkout + end + end + end +end + +SettingsController.send(:include, Checkout::SettingsControllerPatch)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout/settings_helper_patch.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,23 @@ +require_dependency 'settings_helper' + +module Checkout + module SettingsHelperPatch + def self.included(base) # :nodoc: + base.send(:include, InstanceMethods) + + base.class_eval do + alias_method_chain :administration_settings_tabs, :checkout + end + end + + module InstanceMethods + def administration_settings_tabs_with_checkout + tabs = administration_settings_tabs_without_checkout + tabs << {:name => 'checkout', :partial => 'settings/checkout', :label => :label_checkout} + end + end + end +end + +SettingsHelper.send(:include, Checkout::SettingsHelperPatch) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/checkout_helper.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,7 @@ +module CheckoutHelper + class <<self + def supported_scm + Object.const_defined?("REDMINE_SUPPORTED_SCM") ? REDMINE_SUPPORTED_SCM : Redmine::Scm::Base.all + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/tasks/set_default.rake Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,10 @@ +namespace :redmine do + namespace :plugins do + namespace :redmine_checkout do + desc "Sets all repositories to inherit the default setting for the checkout URL." + task :set_default => :environment do + Repository.all.each{|r| r.update_attributes(:checkout_overwrite => "0")} + end + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/lib/tasks/spec.rake Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,14 @@ +begin + require "spec/rake/spectask" + namespace :spec do + namespace :plugins do + desc "Runs the examples for redmine_checkout" + Spec::Rake::SpecTask.new(:redmine_checkout) do |t| + t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""] + t.spec_files = FileList['vendor/plugins/redmine_checkout/spec/**/*_spec.rb'] + end + end + end + task :spec => "spec:plugins:redmine_checkout" +rescue LoadError +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/controllers/repositories_controller_spec.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,48 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe RepositoriesController do + fixtures :settings, :repositories, :projects, :roles, :users, :enabled_modules + integrate_views + + before(:each) do + Setting.default_language = 'en' + User.current = nil + end + + def get_repo + get :show, :id => 1 + end + + it "should display the protocol selector" do + get_repo + response.should be_success + response.should render_template('show') + + response.should have_tag('ul#checkout_protocols') do + with_tag('a[id=?][href=?]', 'checkout_protocol_subversion', "file:///#{RAILS_ROOT.gsub(%r{config\/\.\.}, '')}/tmp/test/subversion_repository") + with_tag('a[id=?][href=?]', 'checkout_protocol_svn+ssh', 'svn+ssh://subversion_repository@svn.foo.bar/svn') + end + end + + it "should display the description" do + get_repo + response.should be_success + response.should render_template('show') + + response.should have_tag('div.repository-info', /Please select the desired protocol below to get the URL/) + end + + it 'should respect the use zero clipboard option' do + Setting.checkout_use_zero_clipboard = '1' + get_repo + response.should be_success + response.should render_template('show') + response.should have_tag('script[src*=?]', 'ZeroClipboard') + + Setting.checkout_use_zero_clipboard = '0' + get_repo + response.should be_success + response.should render_template('show') + response.should_not have_tag('script[src*=]', 'ZeroClipboard') + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/fixtures/enabled_modules.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,5 @@ +--- +enabled_modules_001: + name: repository + project_id: 1 + id: 1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/fixtures/projects.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,13 @@ +--- +projects_001: + created_on: 2006-07-19 19:13:59 +02:00 + name: eCookbook + updated_on: 2006-07-19 22:53:01 +02:00 + id: 1 + description: Recipes management application + homepage: http://ecookbook.somenet.foo/ + is_public: true + identifier: ecookbook + parent_id: + lft: 1 + rgt: 10
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/fixtures/repositories.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,9 @@ +--- +svn: + project_id: 1 + url: file:///<%= RAILS_ROOT.gsub(%r{config\/\.\.}, '') %>/tmp/test/subversion_repository + id: 1 + root_url: file:///<%= RAILS_ROOT.gsub(%r{config\/\.\.}, '') %>/tmp/test/subversion_repository + password: "" + login: "" + type: Subversion
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/fixtures/roles.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,187 @@ +--- +roles_001: + name: Manager + id: 1 + builtin: 0 + permissions: | + --- + - :add_project + - :edit_project + - :manage_members + - :manage_versions + - :manage_categories + - :view_issues + - :add_issues + - :edit_issues + - :manage_issue_relations + - :manage_subtasks + - :add_issue_notes + - :move_issues + - :delete_issues + - :view_issue_watchers + - :add_issue_watchers + - :delete_issue_watchers + - :manage_public_queries + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :edit_time_entries + - :delete_time_entries + - :manage_news + - :comment_news + - :view_documents + - :manage_documents + - :view_wiki_pages + - :export_wiki_pages + - :view_wiki_edits + - :edit_wiki_pages + - :delete_wiki_pages_attachments + - :protect_wiki_pages + - :delete_wiki_pages + - :rename_wiki_pages + - :add_messages + - :edit_messages + - :delete_messages + - :manage_boards + - :view_files + - :manage_files + - :browse_repository + - :manage_repository + - :view_changesets + - :manage_project_activities + + position: 1 +roles_002: + name: Developer + id: 2 + builtin: 0 + permissions: | + --- + - :edit_project + - :manage_members + - :manage_versions + - :manage_categories + - :view_issues + - :add_issues + - :edit_issues + - :manage_issue_relations + - :manage_subtasks + - :add_issue_notes + - :move_issues + - :delete_issues + - :view_issue_watchers + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :edit_own_time_entries + - :manage_news + - :comment_news + - :view_documents + - :manage_documents + - :view_wiki_pages + - :view_wiki_edits + - :edit_wiki_pages + - :protect_wiki_pages + - :delete_wiki_pages + - :add_messages + - :edit_own_messages + - :delete_own_messages + - :manage_boards + - :view_files + - :manage_files + - :browse_repository + - :view_changesets + + position: 2 +roles_003: + name: Reporter + id: 3 + builtin: 0 + permissions: | + --- + - :edit_project + - :manage_members + - :manage_versions + - :manage_categories + - :view_issues + - :add_issues + - :edit_issues + - :manage_issue_relations + - :add_issue_notes + - :move_issues + - :view_issue_watchers + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :manage_news + - :comment_news + - :view_documents + - :manage_documents + - :view_wiki_pages + - :view_wiki_edits + - :edit_wiki_pages + - :delete_wiki_pages + - :add_messages + - :manage_boards + - :view_files + - :manage_files + - :browse_repository + - :view_changesets + + position: 3 +roles_004: + name: Non member + id: 4 + builtin: 1 + permissions: | + --- + - :view_issues + - :add_issues + - :edit_issues + - :manage_issue_relations + - :add_issue_notes + - :move_issues + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :comment_news + - :view_documents + - :manage_documents + - :view_wiki_pages + - :view_wiki_edits + - :edit_wiki_pages + - :add_messages + - :view_files + - :manage_files + - :browse_repository + - :view_changesets + + position: 4 +roles_005: + name: Anonymous + id: 5 + builtin: 2 + permissions: | + --- + - :view_issues + - :add_issue_notes + - :view_gantt + - :view_calendar + - :view_time_entries + - :view_documents + - :view_wiki_pages + - :view_wiki_edits + - :view_files + - :browse_repository + - :view_changesets + + position: 5 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/fixtures/settings.yml Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,115 @@ +--- + settings: + name: plugin_redmine_checkout + value: | + --- !map:HashWithIndifferentAccess + display_checkout_info: "1" + description_Abstract: | + The data contained in this repository can be downloaded to your computer using one of several clients. + Please see the documentation of your version control software client for more information. + + Please select the desired protocol below to get the URL. + display_command_Bazaar: '1' + use_zero_clipboard: "1" + + overwrite_description_Bazaar: "0" + description_Bazaar: "" + display_command_Bazaar: '1' + protocols_Bazaar: + "0": !map:HashWithIndifferentAccess + command: "bzr checkout" + regex: "" + regex_replacement: "" + read_write: readwrite + append_path: "0" + is_default: "1" + protocol: Bazaar + overwrite_description_Cvs: "0" + description_Cvs: "" + display_command_Cvs: '1' + protocols_Cvs: + "0": !map:HashWithIndifferentAccess + command: "cvs checkout" + regex: "" + regex_replacement: "" + read_write: readwrite + append_path: "0" + is_default: "1" + protocol: Cvs + overwrite_description_Darcs: "0" + description_Darcs: "" + display_command_Darcs: '1' + protocols_Darcs: + "0": !map:HashWithIndifferentAccess + command: "darcs get" + regex: "" + regex_replacement: "" + read_write: readwrite + append_path: "0" + is_default: "1" + protocol: Darcs + overwrite_description_Filesystem: "0" + description_Filesystem: "" + display_command_Filesystem: '1' + protocols_Filesystem: !map:HashWithIndifferentAccess + "0": !map:HashWithIndifferentAccess + command: "" + regex: "" + append_path: "0" + is_default: "1" + protocol: Filesystem + access: read+write + regex_replacement: "" + overwrite_description_Git: "0" + description_Git: "" + display_command_Git: '1' + protocols_Git: !map:HashWithIndifferentAccess + "0": !map:HashWithIndifferentAccess + command: "git clone" + regex: "" + append_path: "0" + is_default: "1" + protocol: Git + access: read+write + regex_replacement: "" + overwrite_description_Mercurial: "0" + description_Mercurial: "" + display_command_Mercurial: '1' + protocols_Mercurial: !map:HashWithIndifferentAccess + "0": !map:HashWithIndifferentAccess + command: "hg clone" + regex: "" + append_path: "0" + is_default: "1" + protocol: Mercurial + access: read+write + regex_replacement: "" + display_login: username + overwrite_description_Subversion: "0" + description_Subversion: "" + display_command_Subversion: '1' + protocols_Subversion: !map:HashWithIndifferentAccess + "0": !map:HashWithIndifferentAccess + command: "svn checkout" + regex: foo + append_path: "1" + is_default: "1" + protocol: Subversion + access: permission + regex_replacement: bar + "1": !map:HashWithIndifferentAccess + command: "svn co" + regex: "^.*?([^/]+)/?$" + append_path: "1" + is_default: "0" + protocol: SVN+SSH + access: read-only + regex_replacement: svn+ssh://\1@svn.foo.bar/svn + "2": !map:HashWithIndifferentAccess + command: "svn checkout" + append_path: "0" + is_default: "0" + regex: "" + protocol: Root + access: read+write + regex_replacement: ""
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/macros/macro_spec.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,55 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe "Macros" do + fixtures :settings, :repositories, :projects, :enabled_modules + + include ERB::Util + include ApplicationHelper + include ActionView::Helpers::TextHelper + include ActionView::Helpers::TagHelper + include ActionView::Helpers::UrlHelper + + before(:each) do + Setting.checkout_display_command_Subversion = '0' + + @project = projects :projects_001 + end + + + it "should display default checkout url" do + text = "{{repository}}" + + url = "file:///#{RAILS_ROOT.gsub(%r{config\/\.\.}, '')}/tmp/test/subversion_repository" + textilizable(text).should eql "<p><a href=\"#{url}\">#{url}</a></p>" + end + + it "should display forced checkout url" do + text = "{{repository(svn+ssh)}}" + + url = 'svn+ssh://subversion_repository@svn.foo.bar/svn' + textilizable(text).should eql "<p><a href=\"#{url}\">#{url}</a></p>" + end + + it "should fail without set project" do + @project = nil + + text = "{{repository(svn+ssh)}}" + textilizable(text).should eql "<p><div class=\"flash error\">Error executing the <strong>repository</strong> macro (Checkout protocol svn+ssh not found)</div></p>" + end + + it "should display checkout url from stated project" do + @project = nil + text = "{{repository(ecookbook:svn+ssh)}}" + + url = 'svn+ssh://subversion_repository@svn.foo.bar/svn' + textilizable(text).should eql "<p><a href=\"#{url}\">#{url}</a></p>" + end + + it "should display command" do + Setting.checkout_display_command_Subversion = '1' + + text = "{{repository(svn+ssh)}}" + url = 'svn+ssh://subversion_repository@svn.foo.bar/svn' + textilizable(text).should eql "<p>svn co <a href=\"#{url}\">#{url}</a></p>" + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/models/protocol_spec.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,36 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe Checkout::Protocol do + fixtures :settings, :repositories, :projects, :enabled_modules + + before(:each) do + @admin = User.new + @admin.admin = true + @user = User.new + + @repo = repositories :svn + @repo.url = "http://example.com/svn/testrepo" + end + + it "should use regexes for generated URL" do + protocol = @repo.checkout_protocols.find{|r| r.protocol == "SVN+SSH"} + protocol.url.should eql "svn+ssh://testrepo@svn.foo.bar/svn" + end + + it "should resolve access properties" do + protocol = @repo.checkout_protocols.find{|r| r.protocol == "Subversion"} + protocol.access.should eql "permission" + protocol.access_rw(@admin).should eql "read+write" + + User.current = @user + protocol.access_rw(@user).should eql "read-only" + end + + it "should display the checkout command" do + subversion = @repo.checkout_protocols.find{|r| r.protocol == "Subversion"} + svn_ssh = @repo.checkout_protocols.find{|r| r.protocol == "SVN+SSH"} + + subversion.command.should eql "svn checkout" + svn_ssh.command.should eql "svn co" + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/models/repository_spec.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,49 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe Repository do + fixtures :settings, :repositories + + describe "initialize" do + before(:each) do + @repo = Repository.new() + end + + it "should properly set default values" do + @repo.checkout_overwrite?.should be_false + @repo.checkout_description.should match /Please select the desired protocol below to get the URL/ + @repo.checkout_display_login?.should be_false # no subversion repo + @repo.allow_subtree_checkout?.should be_false + @repo.checkout_protocols.should eql [] + end + end + + describe "subtree checkout" do + before(:each) do + @svn = Repository::Subversion.new + @git = Repository::Git.new + end + it "should be allowed on subversion" do + @svn.allow_subtree_checkout?.should eql true + end + it "should only be possible if checked" do + + end + + it "should be forbidden on git" do + @git.allow_subtree_checkout?.should eql false + end + end + + describe "extensions" do + before(:each) do + @repo = Repository::Subversion.new + end + + it "should provide protocols" do + protocols = @repo.checkout_protocols + protocols[0].protocol.should eql "Subversion" + protocols[1].protocol.should eql "SVN+SSH" + protocols[2].protocol.should eql "Root" + end + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/models/setting_spec.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,14 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe Setting do + fixtures :settings + + before(:each) do + Setting.default_language = 'en' + end + + it "should recognize checkout methods" do + Setting.checkout_display_checkout_info.should eql Setting.plugin_redmine_checkout['display_checkout_info'] + Setting.checkout_display_checkout_info.should eql Setting.plugin_redmine_checkout[:display_checkout_info] + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/sanity_spec.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,11 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe Class do + it "should be a class of Class" do + Class.class.should eql(Class) + end + + it "should be awesome" do + Checkout.awesome?.should be_true + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/spec.opts Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,7 @@ +--colour +--format +progress +--loadby +mtime +--reverse +--backtrace \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/plugins/redmine_checkout/spec/spec_helper.rb Mon Jun 06 14:41:04 2011 +0100 @@ -0,0 +1,27 @@ +ENV['RAILS_ENV'] ||= 'test' + +# prevent case where we are using rubygems and test-unit 2.x is installed +begin + require 'rubygems' + gem "test-unit", "~> 1.2.3" +rescue LoadError +end + +begin + require "config/environment" unless defined? RAILS_ROOT + require RAILS_ROOT + '/spec/spec_helper' +rescue LoadError => error + puts <<-EOS + + You need to install rspec in your Redmine project. + Please execute the following code: + + gem install rspec-rails + script/generate rspec + + EOS + raise error +end + +Fixtures.create_fixtures File.join(File.dirname(__FILE__), "fixtures"), ActiveRecord::Base.connection.tables +require File.join(File.dirname(__FILE__), "..", "init.rb") \ No newline at end of file